sqlite中的锁及概念误区

前言

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

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


需要澄清一下,这种说法自身就有问题,就数据库而言,处理的并发实际上分为读并发,写并发,与读写并发,我们广义上说的并发实际上指的是读写并发,要了解这些,我们还需要先了解一下sqlite中的锁.


sqlite中的锁


sqlite中一共有五种锁分别是

        未加锁(UNLOCKED) 

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

        共享锁(SHARED)

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

        保留锁(RESERVED)

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

        未决锁(PENDING)

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

        排它锁(EXCLUSIVE)

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


读操作锁变化


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

sqlite中的锁及概念误区


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

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

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

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


写操作锁变化


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

sqlite中的锁及概念误区


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

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

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


总结

最后我们来总结一下

[plain] view plain copy
  1. 1.当有写操作时,其他读操作会被驳回  
  2. 2.当有写操作时,其他写操作会被驳回  
  3. 3.当开启事务时,在提交事务之前,其他写操作会被驳回  
  4. 4.当开启事务时,在提交事务之前,其他事务请求会被驳回  
  5. 5.当有读操作时,其他写操作会被驳回  
  6. 6.读操作之间能够并发执行  
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.****.net/zhangsheng_1992/article/details/52598396

前言

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

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


需要澄清一下,这种说法自身就有问题,就数据库而言,处理的并发实际上分为读并发,写并发,与读写并发,我们广义上说的并发实际上指的是读写并发,要了解这些,我们还需要先了解一下sqlite中的锁.


sqlite中的锁


sqlite中一共有五种锁分别是

        未加锁(UNLOCKED) 

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

        共享锁(SHARED)

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

        保留锁(RESERVED)

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

        未决锁(PENDING)

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

        排它锁(EXCLUSIVE)

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


读操作锁变化


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

sqlite中的锁及概念误区


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

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

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

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


写操作锁变化


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

sqlite中的锁及概念误区


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

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

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


总结

最后我们来总结一下

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