[sqlite]锁

前端之家收集整理的这篇文章主要介绍了[sqlite]锁前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

谈及sqlite,首先想到的必定是小巧便捷,尤其是嵌入式开发,相比较而言,对于sqlite的并发,大致都是这么说的(以下不代表个人观点)

     sqlite作为一款小型的嵌入式数据库,本身没有提供复杂的锁定机制,无法内部管理多路并发下的数据操作同步问题,更谈不上优化,
     所以涉及到多路并发的情况,需要外部进行读写锁控制,否则sqlite会返回sqlITE_BUSY错误,以驳回相关请求。

首先需要澄清一下,这种说法自身就有问题,就数据库而言,处理的并发实际上分为读并发,写并发,与读写并发,我们广义上说的并发实际上指的是读写并发,sqlite中的并发操作分为以下几种情况

注意第六条,读操作之间是能够并发执行的为什么呢?要了解这些,我们还需要先了解一下sqlite中的锁,sqlite中一共有五种锁分别是

未加锁(UNLOCKED)

文件没有持有任何锁,即当前数据库不存在任何读或写的操作。其它的进程可以在该数据库上执行任意的读写操作。此状态为缺省状态。

共享锁(SHARED)

在此状态下,该数据库可以被读取但是不能被写入。在同一时刻可以有任意数量的进程在同一个数据库上持有共享锁,因此读操作是并发的。换句话说,只要有一个或多个共享锁处于活动状态,就不再允许有数据库文件写入的操作存在。

保留锁(RESERVED)

假如某个进程在将来的某一时刻打算在当前的数据库中执行写操作,然而此时只是从数据库中读取数据,那么我们就可以简单的理解为数据库文件此时已经拥有了保留锁。当保留锁处于活动状态时,该数据库只能有一个或多个共享锁存在,即同一数据库的同一时刻只能存在一个保留锁和多个共享锁. 需要说明的是update操作 实际上是一个读操作加一个写操作

未决锁(PENDING)

PENDING锁的意思是说,某个进程正打算在该数据库上执行写操作,然而此时该数据库中却存在很多共享锁(读操作),那么该写操作就必须处于等待状态,即等待所有共享锁消失为止,与此同时,新的读操作将不再被允许,以防止写锁饥饿的现象发生。在此等待期间,该数据库文件的锁状态为PENDING,在等到所有共享锁消失以后,PENDING锁状态的数据库文件将在获取排他锁之后进入EXCLUSIVE状态。

排它锁(EXCLUSIVE)

在执行写操作之前,该进程必须先获取数据库的排他锁。然而一旦拥有了排他锁,任何其它锁类型都不能与之共存。因此,为了最大化并发效率,sqlite将会最小化排他锁被持有的时间总量。


了解了sqlite的锁之后 我们再来看针对读写操作,sqlite内部的锁变化



读操作的目的是获取共享锁shared从而来访问数据 那么 在获得共享锁(SHARED)之前

首先检查是否有排它锁(EXCLUSIVE) 如果有 则说明sqlite正在进行写入操作 为保障数据一致 所以无法获取共享锁(SHARED)

如果没有 再检查是否有未决锁(PENDING)如果表示当前有准备进行的写操作并阻止共享锁(SHARED)获取

如果检测不到上述两个锁 将获得共享锁(SHARED) 读取数据 然后释放共享锁


对于写操作,写操作的目的是为了获得 排它锁(EXCLUSIVE) 独占数据库从而一致性,其内部锁变化如下



首先 检查数据库是否有保留锁(RESERVED)排它锁(EXCLUSIVE) 如果有 则说明在此次写操作之前还准备有或者正在进行一次写操作

此时如法获取排它锁(EXCLUSIVE) 如果没有 则获取未决锁(PENDING)未决锁(PENDING)获得时,将无法再获取共享锁(SHARED),也就是说sqlite此时已经不再处理读请求

在持有未决锁(PENDING)期间 将会不断询问内部是否还有共享锁(SHARED) 当等待所有共享锁(SHARED)消失 当所有共享锁(SHARED)消失时 此时锁状态将由未决锁(PENDING)切换至排它锁(EXCLUSIVE) 并写入数据 当排它锁(EXCLUSIVE)激活时 阻止任何类型的其它锁获取 直至写入完毕并释放排它锁(EXCLUSIVE)



最后我们来总结一下

1.当有写操作时,其他读操作会被驳回
2.当有写操作时,其他写操作会被驳回
3.当开启事务时,在提交事务之前,其他写操作会被驳回
4.当开启事务时,在提交事务之前,其他事务请求会被驳回
5.当有读操作时,其他写操作会被驳回
6.读操作之间能够并发执行


关于sqlite事务操作,我将在后续的文章中阐述,请注意关注

猜你在找的Sqlite相关文章