文章目录
问题与原因
最近实施那边反馈,有个别客户明明是把数据保存到数据库,但在界面就是没有呈现出来查询不到数据,为了跟踪排查问题与实施沟通后,决定让客户将数据库导出发回来。
在SQLite Stuido工具可以正常查看该表的所有数据,但用sql语句去查询某条数据时却无法正常访问,抛出如下错误:
Error details: Error while executing SQL query on database database disk image is malformed
经查出现这种错误,通常是数据库文件损坏造成的,至于为什么会出现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