SQLite崩溃处理

SQLite崩溃处理

关于SQLite

SQLite 支持如下三种线程模型

  • 单线程模型 这种模型下,所有互斥锁都被禁用,同一时间只能由一个线程访问。
  • 多线程模型 这种模型下,一个连接在同一时间内只有一个线程使用就是安全的。
  • 串行模型 开启所有锁,可以随意访问。
    设置线程模型

SQLite 可以通过以下三种方式进行线程模型的设置,在实际应用中选择任一一项都可以。

  1. 编译期设定 通过 SQLITE_THREADSAFE 这个参数进行编译器的设定来选择线程模型
  2. 初始化设定 通过调用 sqlite3_config() 可以在 SQLite 初始化时进行设定
  3. 运行时设定 通过调用 sqlite3_open_v2() 接口指定数据库连接的数据库模型
    SQLite 并发和事务

事务

事务是 SQLite 的核心概念。对数据库的操作 (绝大部分) 会被打包成一个事务进行提交,需要注意的是,这里的打包成事务是自动开启的。举例而言,如果简单在一个 for 循环语句里向数据库中插入 10 条数据,意味着将自动生成 10 个事务。但需要注意的是事务是非常耗时的,一般而言, SQLite 每秒能够轻松支持 50000 条的数据插入,但是每秒仅能够支持几十个事务。一般而言,事务速度受限于磁盘速度。所以在批量插入时需要考虑禁用自动提交,将其用 BEGIN ... COMMIT 打包成一个事务。

回滚模式和 WAL

Write-Ahead Log (常简写为 WAL)
为了保证写入正确,SQLite 在使用事务进行数据库改写时将拷贝当前数据库文件的备份,即 rollback journal,当事务失败或者发生意外需要回滚时则将备份文件内容还原到数据库中,并同时删除该日志。这是默认的 DELETE 模式。

而后 SQLite 也引入了 WAL 模式,即 Write-Ahead Log。在这种模式下,所有的修改会写入一个单独的 WAL 文件内。这种模式下,写操作甚至可以不去操作数据库,这使得所有的读操作可以在 "写的同时" 直接对数据库文件进行操作,得到更好的并发性能。

SQLite开启wal代码

SQLiteDatabase dataBase = DataBaseHelper.getWritableDatabase()
SQLiteDatabase dataBase.enableWriteAheadLogging();

锁和并发

SQLite 通过五种锁状态来完成事务。

  • UNLOCKED ,无锁状态。数据库文件没有被加锁。
  • SHARED 共享状态。数据库文件被加了共享锁。可以多线程执行读操作,但不能进行写操作。
  • RESERVED 保留状态。数据库文件被加保留锁。表示数据库将要进行写操作。
  • PENDING 未决状态。表示即将写入数据库,正在等待其他读线程释放 SHARED 锁。一旦某个线程持有 PENDING 锁,其他线程就不能获取 SHARED 锁。这样一来,只要等所有读线程完成,释放 SHARED 锁后,它就可以进入 EXCLUSIVE 状态了。
    EXCLUSIVE 独占锁。表示它可以写入数据库了。进入这个状态后,其他任何线程都不能访问数据库文件。因此为了并发性,它的持有时间越短越好。
    一个线程只有拥有低级别锁时才能够获得更高一级的锁

要保证数据库使用的安全,一般可以采用如下几种模式

SQLite 采用单线程模型,用专门的线程/队列(同时只能有一个任务执行访问) 进行访问
SQLite 采用多线程模型,每个线程都使用各自的数据库连接 (即 sqlite3 *)
SQLite 采用串行模型,所有线程都公用同一个数据库连接。
因为写操作的并发性并不好,当多线程进行访问时实际上仍旧需要互相等待,而读操作所需要的 SHARED 锁是可以共享的,所以为了保证最高的并发性,推荐

使用多线程模式
使用 WAL 模式
单线程写,多线程读 (各线程都持有自己对应的数据库连接)
避免长时间事务
缓存 sqlite3_prepare 编译结果
多语句通过 BEGIN 和 COMMIT 做显示事务,减少多次的自动事务消耗

SQLite错误号

1 #define SQLITE_OK           0   /* 成功 | Successful result */
2 /* 错误码开始 */
3 #define SQLITE_ERROR        1   /* SQL错误 或 丢失数据库 | SQL error or missing database */
4 #define SQLITE_INTERNAL     2   /* SQLite 内部逻辑错误 | Internal logic error in SQLite */
5 #define SQLITE_PERM         3   /* 拒绝访问 | Access permission denied */
6 #define SQLITE_ABORT        4   /* 回调函数请求取消操作 | Callback routine requested an abort */
7 #define SQLITE_BUSY         5   /* 数据库文件被锁定 | The database file is locked */
8 #define SQLITE_LOCKED       6   /* 数据库中的一个表被锁定 | A table in the database is locked */
9 #define SQLITE_NOMEM        7   /* 某次 malloc() 函数调用失败 | A malloc() failed */
10 #define SQLITE_READONLY     8   /* 尝试写入一个只读数据库 | Attempt to write a readonly database */
11 #define SQLITE_INTERRUPT    9   /* 操作被 sqlite3_interupt() 函数中断 | Operation terminated by sqlite3_interrupt() */
12 #define SQLITE_IOERR       10   /* 发生某些磁盘 I/O 错误 | Some kind of disk I/O error occurred */
13 #define SQLITE_CORRUPT     11   /* 数据库磁盘映像不正确 | The database disk image is malformed */
14 #define SQLITE_NOTFOUND    12   /* sqlite3_file_control() 中出现未知操作数 | Unknown opcode in sqlite3_file_control() */
15 #define SQLITE_FULL        13   /* 因为数据库满导致插入失败 | Insertion failed because database is full */
16 #define SQLITE_CANTOPEN    14   /* 无法打开数据库文件 | Unable to open the database file */
17 #define SQLITE_PROTOCOL    15   /* 数据库锁定协议错误 | Database lock protocol error */
18 #define SQLITE_EMPTY       16   /* 数据库为空 | Database is empty */
19 #define SQLITE_SCHEMA      17   /* 数据结构发生改变 | The database schema changed */
20 #define SQLITE_TOOBIG      18   /* 字符串或二进制数据超过大小限制 | String or BLOB exceeds size limit */
21 #define SQLITE_CONSTRAINT  19   /* 由于约束违例而取消 | Abort due to constraint violation */
22 #define SQLITE_MISMATCH    20   /* 数据类型不匹配 | Data type mismatch */
23 #define SQLITE_MISUSE      21   /* 不正确的库使用 | Library used incorrectly */
24 #define SQLITE_NOLFS       22   /* 使用了操作系统不支持的功能 | Uses OS features not supported on host */
25 #define SQLITE_AUTH        23   /* 授权失败 | Authorization denied */
26 #define SQLITE_FORMAT      24   /* 附加数据库格式错误 | Auxiliary database format error */
27 #define SQLITE_RANGE       25   /* 传递给sqlite3_bind()的第二个参数超出范围 | 2nd parameter to sqlite3_bind out of range */
28 #define SQLITE_NOTADB      26   /* 被打开的文件不是一个数据库文件 | File opened that is not a database file */
29 #define SQLITE_ROW         100  /* sqlite3_step() 已经产生一个行结果 | sqlite3_step() has another row ready */
30 #define SQLITE_DONE        101  /* sqlite3_step() 完成执行操作 | sqlite3_step() has finished executing */

Android版本与SQLite版本对应关系

Android SQLite
API 27 3.19
API 26 3.18
API 24 3.9
API 21 3.8
API 11 3.7
API 8 3.6
API 3 3.5
API 1 3.4

你可能感兴趣的:(SQLite崩溃处理)