版权声明:博客将逐步迁移到 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

讨论SQLite数据库损坏与修复的更多相关文章

  1. SQLite数据库损坏及其修复探究

    数据库如何发生损坏   SQLite 数据库具有很强的抗损坏能力.在执行事务时如果发生应用程序崩溃.操作系统崩溃甚至电源故障,那么在下次访问数据库文件时,会自动回滚部分写入的事务.恢复过程是全自动的, ...

  2. SQL Server数据库损坏、检测以及简单的修复办法

    简介     在一个理想的世界中,不会存在任何数据库的损坏,就像我们不会将一些严重意外情况列入我们生活中的日常一样,而一旦这类事情发生,一定会对我们的生活造成非常显著的影响,在SQL Server中也 ...

  3. 修复 SQLite 数据库文件

    目 录 第1章 说明    1 1 下载SQLite Tools    1 2 运行    2 第1章 说明 笔者编写的一个程序,无法往 SQLite 数据库文件里写数据.使用SQLiteSpy打开该 ...

  4. 微信 SQLite 数据库修复实践

    1.前言 众所周知,微信在后台服务器不保存聊天记录,微信在移动客户端所有的聊天记录都存储在一个 SQLite 数据库中,一旦这个数据库损坏,将会丢失用户多年的聊天记录.而我们监控到现网的损坏率是0.0 ...

  5. Sql server Compact 小型数据库损坏修复

    之前碰到过小型数据库损坏打不开的问题,一直没有理会,今天生产上客户本地小库产生这样的问题,已经修复         SqlCeEngine engine = new SqlCeEngine(" ...

  6. sql2005数据库置疑修复断电崩溃索引损坏 数据库索引错误修复/数据库表损坏/索引损坏/系统表混乱等问题修复

    sql2005数据库置疑修复断电崩溃索引损坏 数据库索引错误修复/数据库表损坏/索引损坏/系统表混乱等问题修复 客 户 名 称 济南某电子商务公司 数 据 类 型 SQL2005数据库 故 障 检 测 ...

  7. Sqlite 数据库出现database disk image is malformed报错的解决方法

    软件用的是Sqlite数据库,昨天还好好的,今天开机登录软件报错:database disk image is malformed 用Sqlite Expert Personal 重建索引,发现其中一 ...

  8. sqlite 数据库错误 The database disk image is malformed database disk image

    收银机上的sqlite数据库经常出现这种错误,错误的原因有可能是突然断电或是一些不规范操作导致的. 网上一般的做法有两种: 方法一: 1.在https://www.sqlite.org/downloa ...

  9. SQLite 数据库调研

    SQLite数据库的特点(转载的): ★技术上的优点和特性 SQLite是一个轻量级.跨平台的关系型数据库.既然号称关系型数据库,支持SQL92标准中常用的玩意儿(比如视图.事务.触发器等)就是理所当 ...

随机推荐

  1. 关于js异步的一些知识点

    1,什么是单线程,和异步有什么关系 单线程-只有一个线程,只能做一件事 单线程的原因:避免DOM 渲染的冲突 浏览器需要渲染DOM JS 可以修改DOM 结构 JS 执行的时候,浏览器DOM 渲染会暂 ...

  2. 与app交互因异步造成的坑记录

    一.问题产生背景: 在app内跳转到H5页面,初始页面获取用户等各种信息,前端除了可以获取链接上的参数去请求接口,接着进行数据的缓存等,也可以去获取app写入window的数据,然后进行其他的操作.公 ...

  3. eclipse导入项目后出现红色叉号的解决方案

    对于一名程序员来说,我导入的项目在项目的名称上无端加了一个红色的叉号,虽然这个不友好的符号,对于我整个的项目运行没有任何影响,但是总让我觉得不舒服,大大的叉号写在我的项目的脑袋上,我心里能舒服吗?于是 ...

  4. zookeeper:1

    分布式环境的特点 分布性:多台机器位置不同,但是相互协同做某一件事情. 并发性:程序运行过程中,并发性操作是很长见的.比如:同一个分布式系统中的多个节点,同时访问一个共享资源.(数据库,分布式存储) ...

  5. IntelliJ IDEA详细配置和使用教程(适用于Java开发人员)

    关闭Intellij IDEA自动更新在File->Settings->Appearance & Behavior->System Settings->Updates下 ...

  6. Cannot debug in IntellijIdea on Linux

    OS: Deepin LinuxIDE: Intellij IdeaProject: SpringBoot based maven project Issue: cannot debug in Ide ...

  7. 【转】Java8中list转map方法总结

    https://blog.csdn.net/zlj1217/article/details/81611834 背景在最近的工作开发之中,慢慢习惯了很多Java8中的Stream的用法,很方便而且也可以 ...

  8. Linux使用帮助详解

    主要内容:                    whatis                    command --help                     man and info   ...

  9. Lua 学习之基础篇七<Lua Module,Package介绍>

    Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require ...

  10. linux学习-添加多个硬盘和lvm配置

    原文 一般,服务器会有多个硬盘,一块硬盘分区安装操作系统,另外多块硬盘分区做存储使用.现在测试添加多块硬盘分区,使用lvm进行实现动态磁盘分配. 1.新增硬盘查看 fdisk -l 可以看到新增的两块 ...