加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

讨论SQLite数据库损坏与修复

发布时间:2020-12-12 23:48:06 所属栏目:百科 来源:网络整理
导读:昨晚,朋友和我反馈SQLite数据库发生损坏有没有办法恢复。大致的情况是这样的,当数据库在使用时不小心用了新的文件覆盖数据库,导致了SQLite数据库出现了损坏,打开的时候出现要输入密码,而且不能把SQL语句dump下来。所以,文章这里整理SQLite数据库出现损
昨晚,朋友和我反馈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:&;sqlite3mydata.db .dump >mydata.sql d:&;sqlite3new.db <mydata.sql d:&;sqlite3 aa.db "pragma integrity_check"

这里可以下载 sqlite3.exe 当然,这些API只是在一定程序修复损坏的数据库,无法解决所有的问题。

SQLite使用建议

这里有4点建议: 1. 减少多进程或多线程操作,尽可能单线程写。 2. 减少事务操作,减小事务复杂度,减少检查点 3. 减少数据库的大小 4. 避免使用PRAGMA synchronous=OFF
参考:http://blog.csdn.net/mycwq/article/details/45541409

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读