提到锁就不得不说到死锁的问题,而SQLite也可能出现死锁。
下面举个例子:
连接1:BEGIN (UNLOCKED)
连接1:SELECT ... (SHARED)
连接1:INSERT ... (RESERVED)
连接2:BEGIN (UNLOCKED)
连接2:SELECT ... (SHARED)
连接1:COMMIT (PENDING,尝试获取EXCLUSIVE锁,但还有SHARED锁未释放,返回SQLITE_BUSY)
连接2:INSERT ... (尝试获取RESERVED锁,但已有PENDING锁未释放,返回SQLITE_BUSY)
现在2个连接都在等待对方释放锁,于是就死锁了。当然,实际情况并没那么糟糕,任何一方选择不继续等待,回滚事务就行了。

不过要更好地解决这个问题,就必须更深入地了解事务了。
实际上BEGIN语句可以有3种起始状态:
DEFERRED:默认值,开始事务时不获取任何锁。进行第一次读操作时获取SHARED锁,进行第一次写操作时获取RESERVED锁。
IMMEDIATE:开始事务时获取RESERVED锁。
EXCLUSIVE:开始事务时获取EXCLUSIVE锁。

现在考虑2个事务在开始时都使用IMMEDIATE方式:
连接1:BEGIN IMMEDIATE (RESERVED)
连接1:SELECT ... (RESERVED)
连接1:INSERT ... (RESERVED)
连接2:BEGIN IMMEDIATE (尝试获取RESERVED锁,但已有RESERVED锁未释放,因此事务开始失败,返回SQLITE_BUSY,等待用户重试)
连接1:COMMIT (EXCLUSIVE,写入完成后释放)
连接2:BEGIN IMMEDIATE (RESERVED)
连接2:SELECT ... (RESERVED)
连接2:INSERT ... (RESERVED)
连接2:COMMIT (EXCLUSIVE,写入完成后释放)
这样死锁就被避免了。

而EXCLUSIVE方式则更为严苛,即使其他连接以DEFERRED方式开启事务也不会死锁:
连接1:BEGIN EXCLUSIVE (EXCLUSIVE)
连接1:SELECT ... (EXCLUSIVE)
连接1:INSERT ... (EXCLUSIVE)
连接2:BEGIN (UNLOCKED)
连接2:SELECT ... (尝试获取SHARED锁,但已有EXCLUSIVE锁未释放,返回SQLITE_BUSY,等待用户重试)
连接1:COMMIT (EXCLUSIVE,写入完成后释放)
连接2:SELECT ... (SHARED)
连接2:INSERT ... (RESERVED)
连接2:COMMIT (EXCLUSIVE,写入完成后释放)
不过在并发很高的情况下,直接获取EXCLUSIVE锁的难度比较大;而且为了避免EXCLUSIVE状态长期阻塞其他请求,最好的方式还是让所有写事务都以IMMEDIATE方式开始。
顺带一提,要实现重试的话,可以使用sqlite3_busy_timeout()或sqlite3_busy_handler()函数。

由此可见,要想保证线程安全的话,可以有这4种方式:

  • SQLite使用单线程模式,用一个专门的线程访问数据库。
  • SQLite使用单线程模式,用一个线程队列来访问数据库,队列一次只允许一个线程执行,队列里的线程共用一个数据库连接。
  • SQLite使用多线程模式,每个线程创建自己的数据库连接。
  • SQLite使用串行模式,所有线程共用全局的数据库连接。

作者:Crazy2015
链接:https://www.jianshu.com/p/15051fbd5a35
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

SQLite也可能出现死锁的更多相关文章

  1. 《JAVA高并发编程详解》-程序可能出现死锁的场景

  2. SQLite在多线程环境下的应用

    文一 SQLite的FAQ里面已经专门说明,先贴出来.供以后像我目前的入门者学习. (7) 多个应用程序或者同一个应用程序的多个例程能同时存取同一个数据库文件吗? 多进程可以同时打开同一个数据库,也可 ...

  3. iOS sqlite3数据库解析

    看来从版本3.3.1基本上已经支持线程句柄的传递功能.具体限制我标记了一下.(6) Is SQLite threadsafe?SQLite is threadsafe. We make this co ...

  4. sqlite3 多线程和锁 ,优化插入速度及性能优化

    一. 是否支持多线程?   SQLite官网上的"Is SQLite threadsafe?"这个问答. 简单来说,从3.3.1版本开始,它就是线程安全的了.而iOS的SQLite ...

  5. Java:多线程<三>死锁、线程间通讯

    死锁: 同步嵌套同步,而且使用的锁不是同一把锁时就可能出现死锁 class Test implements Runnable { private boolean flag; Test(boolean ...

  6. [翻译]:SQL死锁-阻塞

    一般情况下死锁不是一步到位的,它必须满足特定的条件,然后形成资源的循环依赖才会产生死锁,死锁之前一定会出现阻塞,由阻塞升级才有可能出现死锁,所以我们有必要了解系统中都有哪些已经被阻塞的锁. 我在解决共 ...

  7. java 死锁及解决

    Java线程死锁如何避免这一悲剧  Java线程死锁需要如何解决,这个问题一直在我们不断的使用中需要只有不断的关键.不幸的是,使用上锁会带来其他问题.让我们来看一些常见问题以及相应的解决方法: Jav ...

  8. SQL Server 死锁概念和分析

    锁的概念 锁是什么 锁是数据库中在并发操作情形下保护资源的机制.通常(具体要看锁兼容性)只有锁的拥有者才能对被锁的资源进行操作,从而保证数据一致性. 锁的概念可分为几部分 锁资源(锁住什么) 锁模式( ...

  9. java 线程的死锁问题

    以下的情况可能出现死锁 1.一个对象的同步方法去调用另一个对象的同步方法,同时另一个对象的同步方法也在调用这个对象的同步方法,导致一定几率的死锁,不一定每次都会出现死锁,模拟的代码如下 package ...

随机推荐

  1. mybatis整合springboot 以及需要注意的细节

    具体怎么整合的网上有很多优秀的博客介绍,这里就直接引用一篇个人觉得非常详细的教程: https://blog.csdn.net/winter_chen001/article/details/77249 ...

  2. 列表 ul ol dl 和 块级标签和行及标签之间的转换

    1. 无序列表 有序列表 自定义列表 1,无序列表 第一 你不必须有子标签  <li></li> 第二 ul天生自带内外边距 List-style的属性值 circle(空心圆 ...

  3. js 常用正则表达式

    1 用户名正则 //用户名正则,4到16位(字母,数字,下划线,减号) var uPattern = /^[a-zA-Z0-9_-]{4,16}$/; //输出 true console.log(uP ...

  4. JS中的可枚举属性与不可枚举属性以及扩展

    在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的.可枚举性决定了这个属性能否被for…in查找遍历到. 一.怎么判断属性是否可枚举 js中基本包 ...

  5. Win7怎么录制电脑屏幕视频

    我们在看视频的时候,经常会看到自己特别喜爱的视频,想要把其中的某些片段给录制下来,那么Win7怎么录制电脑屏幕视频?其实步骤很简单,下面就来分享下具体的步骤. 使用工具: 电脑 操作方法: 第一步.首 ...

  6. FUNCTIONALITY OF ITEM CATEGORY

    Item Category Purpose This wiki page will breify discuss about functionality of Item Category in SAP ...

  7. Salesforce 外部对象

    外部对象(External Object) 在Salesforce中,管理员或开发者可以通过"外部对象"将其他系统中的数据虚拟地展现为Salesforce的对象.每个外部对象都要连 ...

  8. ACL技术总结

    1.ACL的全称是访问控制列表,本质上是定义一组策略,以便指导报文在交换机内部的转发行为. 2.要配置策略,首先要明确ACL应用的对象,可以是针对端口,也可以是针对特殊的一条流. 针对端口,就是指端口 ...

  9. 常用的JVM调优参数总结汇总【随时查阅学习】

    本文章参数根据后期用的参数会持续更新  --- (1)-Xms20M 表示设置JVM启动内存的最小值为20M,必须以M为单位 (2)-Xmx20M 表示设置JVM启动内存的最大值为20M,必须以M为单 ...

  10. 30分钟彻底弄懂flex布局

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由elson发表于云+社区专栏 目前在不考虑IE以及低端安卓机(4.3-)的兼容下,已经可以放心使用flex进行布局了.什么是flex布 ...