问题与原因

最近实施那边反馈,有个别客户明明是把数据保存到数据库,但在界面就是没有呈现出来查询不到数据,为了跟踪排查问题与实施沟通后,决定让客户将数据库导出发回来。

在SQLite Stuido工具可以正常查看该表的所有数据,但用sql语句去查询某条数据时却无法正常访问,抛出如下错误:

 Error details: Error while executing SQL query on database  database disk image is malformed

经查出现这种错误,通常是数据库文件损坏造成的,至于为什么会出现SQLite数据库被损坏,官方解释:

SQLite 数据库具有很强的抗损坏性。如果应用程序崩溃,或操作系统崩溃,甚至在事务过程中发生电源故障,则应在下次访问数据库文件时自动回滚部分写入的事务。恢复过程是全自动的,不需要用户或应用程序的任何操作。尽管 SQLite 可以抵抗数据库损坏,但它也不能幸免。 以下任何一种原因可能会损坏数据库文件。

  • 文件被流氓线程或进程覆盖
  • 文件锁定问题,如果没有协调,两个线程或进程可能会尝试同时对数据库文件进行不兼容的更改,从而导致数据库损坏,也就是说多个线程对同一个资源访问,如果不同步数据库可能也会损坏。
  • 同步失败
  • 磁盘驱动器和闪存故障
  • 内存损坏
  • 操作系统问题
  • SQLite 的错误

如何损坏 SQLite 数据库文件

修复数据库

虽然SQLite数据库能够被修复正常使用,但可能会存在数据丢失的问题,对于这种情况也是无能为力啊

进入正题吧,网上有基本上是这两种修复方案:

  • 命令行修复
  • 使用SQLite Expert Professional 的Repair功能进行修复,注意这是专业版,要收费的,不是免费版。

命令行修复

通过dump命令就是从一个原数据库文件中,将其所有执行过的sql语句全部dump下来,并放到一个临时文件tmp.sql中,然后新建一个空数据库文件,通过read命令读取tmp.sql文件将数据写入到空数据库文件中。

一、准备

以windows系统为例,在SQLite的官方网站下载sqlite-tools-win32-x86-3360000.zip
在这里插入图片描述
然后将被损坏的数据拷贝到sqlite-tools-win32-x86-3360000.zip的解压目录下:
在这里插入图片描述

二、命令行打开被损坏的数据库文件

双击sqlite3.exe程序,用.open命令行读取被损坏的数据库文件

sqlite>.open xxx

xxx是数据库名称

三、导出sql语句到临时文件
sqlite>.output tmp.sql
sqlite>.dump
sqlite>.quit

tmp.sql文件生成在sqlite-tools-win32-x86-3360000目录下

在这里插入图片描述

四、 修改tmp.sql文件与写入到空数据库中

由于数据库文件损坏,所以sqlite自动将tmp.sql最后一行加上了一句Rollback,因此我们需要手动修改tmp.sql文件,将最后一行的Rollback改为Commit;。

用记事本或其他软件将tmp.sql文件打开修改,然后保存。
在这里插入图片描述
再次双击打开sqlite3.exe,使用.open命令行创建一个空数据库

sqlite> .open newDB.db

会生成一个空数据库newDB.db
在这里插入图片描述
接着使用.read命令行读取tmp.sql并写入到空数据库中。

sqlite>.read tmp.sql
sqlite>.quit

在读取tmp.sql文件中可能报错,根据提示找到目标行数修改并保存,再执行命令行.read;如果在写入中没有报错就不用去修改tmp.sql文件中sql语句,这是理想的状态。

sqlite> .read tmp.sql
Error: near line 33524: UNIQUE constraint failed: log_data.id
Error: near line 33525: UNIQUE constraint failed: log_data.id
Error: near line 33526: UNIQUE constraint failed: log_data.id
Error: near line 33527: UNIQUE constraint failed: log_data.id
Error: near line 33528: UNIQUE constraint failed: log_data.id
Error: near line 33529: UNIQUE constraint failed: log_data.id
Error: near line 33530: UNIQUE constraint failed: log_data.id
Error: near line 33531: UNIQUE constraint failed: log_data.id
Error: near line 33532: UNIQUE constraint failed: log_data.id
Error: near line 33533: UNIQUE constraint failed: log_data.id

到这里就完成数据库的修复,在newDB.db数据库文件就会有数据了,虽然修复了,文件的大小却小了,很明显有数据丢失。
在这里插入图片描述

SQLite Expert Professional 修复

之前一直使用SQLiteStudio GUI可视化软件来查看数据库,有一个很好导出功能。

SQLite Expert Professional专业版的安装与注册,专业版是收费的,如何绕过,请参考这篇:SQLite Expert安装与注册

用SQLite Expert Professional修复就很简单了,打开待修复的数据库文件,然后选择Repair功能即可
在这里插入图片描述
点击Repair,选择修复后数据库导出的目录与名称。

在这里插入图片描述
如果数据库文件比较大的话,会修复等待的时间会长些。修复前后的文件对比:
在这里插入图片描述
与命令行修复相比,文件大小更小些,可预见丢失的数据会更多,实际也确实是这样的,个人建议还是使用命令行修复,虽然操作复杂些,但数据更珍贵。

参考

https://www.sqlite.org/howtocorrupt.html
https://blog.csdn.net/fangye945a/article/details/94762526
https://www.jianshu.com/p/d2c53d654e4a

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐