Sqlite事务锁
Sqlite事务中锁的状态
- 1 UNLOCKED: 表示数据库并未开启任何读写, 使用
BEGIN
开启一个事务时就是该状态 - 2 SHARED:
Sqlite
可以同时多线程读取, 再进行SELECT
操作就会获得该锁, 同时可以被多线程事务持有 - 3 RESERVED: 表示数据库准备写入数据库, 同一时间只能被一个持有, 但是并不禁止持有
SHARED
锁 - 4 PENDING: 在真正写入之前等待其他
SHARED
的释放 - 5 EXCLUSIV: 表示可以写入数据库了, 其他线程不再能对数据库进行任何读写操作了
一个事务
BEGIN(UNLOCKED)
SELECT...(SHARED)
INSERT...(RESERVED)
COMMIT(PENDING)
一个事务大致会经过如上流程进行一个修改数据库操作, 但是我们可以看到: 在COMMIT
时需要等待其他线程释放SHARED
锁, 那么假设另外一个事务进行了读取操作下一步等待进行插入操作, 那么就进入了死锁
//线程1 //线程2
BEGIN(UNLOCKED)
BEGIN(UNLOCKED)
SELECT...(SHARED)
SELECT...(SHARED)
INSERT...(RESERVED)
COMMIT(PENDING)...
INSERT...
COMMIT
和INSERT
各自等待对方的锁释放, 造成了死锁
BEGIN
起始状态
- 1
BEGIN
不获取任何锁 - 2
BEGIN IMMEDIATE
: 开启时获取RESERVED
锁, - 3
BEGING EXCLUSIVE
: 开启时获取EXCLUSIV
锁
RESERVED
同时不允许多个获取, 所以不允许同时开启两个IMMEDIATE
方式的事务; EXCLUSIVE
方式来说, 即使使用BEGIN
开启了另外一个事务, 也无法进行任何查看更改操作了
如果把SQlite数据库用于特别复杂或要求很高的场景, 其多线程的安全使用还是很需要考量的!
总结
- 1 如果要求不高的情况下可以使用序列化的方式, 全局使用同一个连接
- 2 如果对多线程有要求的话, 建议使用一个单线程独立访问数据库
- 3 Sqlite所谓的线程安全保障的时数据库的安全, 而并不保证语句的正确执行; 实际工作中往往需要的时即使短时间阻塞或者延时但是语句能够执行下去
网友评论