讨论SQLite数据库损坏与修复

 

版权声明:博客将逐步迁移到 http://cwqqq.com https://blog.csdn.net/cwqcwk1/article/details/45541409
昨晚,朋友和我反馈SQLite数据库发生损坏有没有办法恢复。大体的状况是这样的,当数据库在使用时不当心用了新的文件覆盖数据库,致使了SQLite数据库出现了损坏,打开的时候出现要输入密码,并且不能把SQL语句dump下来。因此,文章这里整理SQLite数据库出现损坏的全部状况,以及如何修复损坏的SQLite数据库文件。
 
SQLite算是很是稳定的数据库,不容易出现损坏,就算应用程序崩溃,或者操做系统崩溃,甚至是执行事务时出现断电,都能在下一次使用数据库时自动修复。可是,仍是不能避免不出现损坏的状况。
 

致使SQLite数据库损坏的状况

致使SQLite数据库损坏的状况大体可归结为4类:文件覆盖问题、文件锁问题、数据同步问题、内存问题
 

文件覆盖问题

SQLite数据库文件被覆盖是可能的,毕竟是一个普通的磁盘文件,意味着全部的进程均可以打开和覆盖,因此不可能彻底避免文件覆盖的状况。
1. 多线程写数据库问题。
  SQLite数据库是支持多进程并发读写,可是若是这时候关闭和从新打开数据库,就极可能出现一些线程还在写数据到数据库,出现部分数据被覆盖的状况。
 
2. 执行事务时备份或恢复数据
  事务都是一个过程性的操做,须要必定时间,而数据备份是原子操做,若是在事务执行过程时备份,可能致使复制的内容包含了部分新的内容和部分旧的内容,就出现数据库损坏。恢复也是同样。
 
3. 删除日志文件
  SQLite数据库一般都是存储全部内容到一个文件,但执行事务时,为了实现程序崩溃,断电时能够回滚日志,就伴随着一些附加的日志文件。若是日志被删除了,就会致使恢复出现异常。
 

文件锁问题

为了实现SQLite数据库并发读写,SQLite会使用文件锁来保证数据安全。
1. 系统文件锁问题
SQLite依赖于底层的文件系统对文件锁的实现,可是,一些文件系统存在锁逻辑错误,使得锁并不可靠,这在网络文件系统和NFS状况比较常见。
 
2. POSIX协同锁(advisory lock)
在linux 或者unix下,SQLite 默认锁是协同锁。当进程使用协同锁,若是其中有一个线程执行 close() 就可能致使锁被取消。若是已经有两个线程同时链接到同一个数据库,再来一个线程不以SQLite API的形式,就是以系统文件形式读取数据库( open(),  read() ,  而后close()),就会致使这个进程的数据库锁被取消,而两个线程同时操做数据库就会致使数据覆盖引发错乱。
 
3. 不一样的链接协议
不一样的链接协议锁也可能会不一样,也就致使锁没有发挥错误引发错误。
 
4.当数据库正在使用时删除或重命名数据库文件
出现这种状况每每是在linux等类POSIX系统,windows下不会出现这个状况,并且同时有事务执行就会放大这个问题。
 

数据同步问题

为了保证数据一致性,SQLite有时候会请求操做系统将全部等待持久化的数据刷入磁盘,而后等待这个操做完成。
1.磁盘驱动器的同步请求多是不可靠的
 现有普通消费级别的磁盘驱动器多数都会谎报数据同步结果,以指望获得更高的写入速度。当数据刚到达磁盘缓冲区,还没真正写入氧化物介质,磁盘驱动器就报告内容已经安全写入。可是这时候断电、硬件复位就会致使数据同步失败。这种状况主要出如今闪存介质。
 
2.使用PRAGMAs会影响同步
经过设置PRAGMA synchronous=OFF, SQLite全部的同步操做都会被忽略。这使得SQLite运行得更快,但若是出现电源故障或硬件复位就会前面保存的全部数据。若是单纯为了得到最大的数据可靠性和健壮性,SQLite可设置synchronous = FULL
 

内存问题

SQLite做为一个C运行库,和使用它的应用程序运行在同一个内存地址空间。这意味着,任何野指针,缓冲区溢出,堆损坏等都有可能损坏了SQLite的数据结构,并最终致使数据库文件损坏。
另外,使用 内存映射I/O模型(如mmap)的时候,内存问题会变得更加严重。当数据库文件的一部分或所有被映射到应用程序的地址空间,虽然减小了文件IO操做,可是野指针可能访问并修改到任何部分的映射空间数据。
 
更多SQLite数据库损坏的缘由能够看 这里
 
 

修复损坏的SQLite数据库

linux下:
$ sqlite3 mydata.db ".dump" | sqlite3 new.db
win下:
d:\>sqlite3 mydata.db .dump > mydata.sql
d:\>sqlite3 new.db < mydata.sql
d:\>sqlite3 aa.db "pragma integrity_check"
 
这里能够下载 sqlite3.exe
固然,这些API只是在必定程序修复损坏的数据库,没法解决全部的问题。
 

SQLite使用建议

这里有4点建议:
1. 减小多进程或多线程操做,尽量单线程写。
2. 减小事务操做,减少事务复杂度,减小检查点
3. 减小数据库的大小
4. 避免使用PRAGMA synchronous=OFF
相关文章
相关标签/搜索