多线程下的Sqlite
最近在多线程并发执行的情况下, 碰到了
database is lock
导致操作被驳回
Sqlite多线程安全吗?
在编译时可以设置线程模式, 可以编译为线程安全的
Sqlite线程模式
Sqlite的线程模式是在编译时确定的, 通过编译参数设置
- 1
-DSQLITE_THREADSAFE = 0
: 单线程模式, 所有互斥锁均被禁用多线程使用不安全 - 2
-DSQLITE_THREADSAFE = 2
: 多线程模式, 只要一个数据库连接不被多个线程同时使用就是安全的 - 3
-DSQLITE_THREADSAFE = 1
: 串行模式, 保证线程安全
锁:bCoreMutex
和bFullMutex
, 多线程模式仅开启bCoreMutex
(这两种锁之后再介绍)
可以使用int sqlite3_threadsafe(void);
获取线程模式, 模式模式是序列化
后两种模式之间可以进行设置
如果设置为多线程模式或者串行模式, 那么可以通过
sqlite3_config
或者sqlite3_open_v2
指定线程模式(两种模式之一)
int sqlite3_config(int, ...);
sqlite
的全局设定, 请注意线程安全; 设置线程模式可选的参数SQLITE_CONFIG_SINGLETHREAD
,SQLITE_CONFIG_MULTITHREAD
,SQLITE_CONFIG_SERIALIZED
, 注意应当在数据库初始化之前执行, 最好在程序开头执行,
int sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
);
第三个参数, 传入SQLITE_OPEN_NOMUTEX
或者SQLITE_OPEN_FULLMUTEX
分别指明多线程模式和串行模式
Sqlite的线程安全
设置正确的前提下,多线程同时访问SQLite并不会影响数据库的完整性,而是说每个线程的数据库操作都可以正确执行; 实际上两个线程同时操作数据库的话, 有可能直接返回database is lock
或者SQLITE_BUSY
驳回请求
我们的实际的要求应当是阻塞等待最后执行, 如果线程模式和使用设置不当的话就很有出现错误
解决方案
首先, 序列化模式不在我们考虑范围内, 那么通常办法是:
- 1 手动加锁
- 2 建立操作队列, 统一操作数据库
锁的机制
- 1 当有写操作时,其他读操作会被驳回
- 2 当有写操作时,其他写操作会被驳回
- 3 当开启事务时,在提交事务之前,其他写操作会被驳回
- 4 当开启事务时,在提交事务之前,其他事务请求会被驳回
- 5 当有读操作时,其他写操作会被驳回
- 6 读操作之间能够并发执行
扩展: 多进程
多进程同时操作数据库时应当是采用了文件锁, 能够多进程读取但仅单进程写入, 同时需要注意文件系统的问题.
网友评论