SQLite也可能出现死锁
提到锁就不得不说到死锁的问题,而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也可能出现死锁的更多相关文章
- 《JAVA高并发编程详解》-程序可能出现死锁的场景
- SQLite在多线程环境下的应用
文一 SQLite的FAQ里面已经专门说明,先贴出来.供以后像我目前的入门者学习. (7) 多个应用程序或者同一个应用程序的多个例程能同时存取同一个数据库文件吗? 多进程可以同时打开同一个数据库,也可 ...
- iOS sqlite3数据库解析
看来从版本3.3.1基本上已经支持线程句柄的传递功能.具体限制我标记了一下.(6) Is SQLite threadsafe?SQLite is threadsafe. We make this co ...
- sqlite3 多线程和锁 ,优化插入速度及性能优化
一. 是否支持多线程? SQLite官网上的"Is SQLite threadsafe?"这个问答. 简单来说,从3.3.1版本开始,它就是线程安全的了.而iOS的SQLite ...
- Java:多线程<三>死锁、线程间通讯
死锁: 同步嵌套同步,而且使用的锁不是同一把锁时就可能出现死锁 class Test implements Runnable { private boolean flag; Test(boolean ...
- [翻译]:SQL死锁-阻塞
一般情况下死锁不是一步到位的,它必须满足特定的条件,然后形成资源的循环依赖才会产生死锁,死锁之前一定会出现阻塞,由阻塞升级才有可能出现死锁,所以我们有必要了解系统中都有哪些已经被阻塞的锁. 我在解决共 ...
- java 死锁及解决
Java线程死锁如何避免这一悲剧 Java线程死锁需要如何解决,这个问题一直在我们不断的使用中需要只有不断的关键.不幸的是,使用上锁会带来其他问题.让我们来看一些常见问题以及相应的解决方法: Jav ...
- SQL Server 死锁概念和分析
锁的概念 锁是什么 锁是数据库中在并发操作情形下保护资源的机制.通常(具体要看锁兼容性)只有锁的拥有者才能对被锁的资源进行操作,从而保证数据一致性. 锁的概念可分为几部分 锁资源(锁住什么) 锁模式( ...
- java 线程的死锁问题
以下的情况可能出现死锁 1.一个对象的同步方法去调用另一个对象的同步方法,同时另一个对象的同步方法也在调用这个对象的同步方法,导致一定几率的死锁,不一定每次都会出现死锁,模拟的代码如下 package ...
随机推荐
- A simple problem(湘大邀请赛)
A simple problem Accepted : 61 Submit : 418 Time Limit : 15000 MS Memory Limit : 655360 KB Probl ...
- Hibernate入门(二)——hibernateAPI详解
Hibernate API 详解 1.Configuration 功能:配置加载类,用于加载主配置,orm元数据加载 .创建: Configuration conf = new Configurati ...
- javascript html页面中的内容替换
<script language="javascript"> function ffRed(){ var xsxf = document.getElementById ...
- Java 原生网络编程.
一.概念 Java 语言从其诞生开始,就和网络紧密联系在一起.在 1995 年的 Sun World 大会上,当时占浏览器市场份额绝对领先的网景公司宣布在浏览器中支持Java,从而引起一系列的公司产品 ...
- 3;XHTML排列清单控制标记
1.无序号条例式清单<ul> 2.有序号条例式清单<ol> 3.无序列表和有序列表的结合应用 4.叙述式清单<dl> 排列清单控制标记可以创建一般的列表.编号列表或 ...
- JavaScript碎片—函数闭包(模拟面向对象)
经过这几天的博客浏览,让我见识大涨,其中有一篇让我感触犹深,JavaScript语言本身是没有面向对象的,但是那些大神们却深深的模拟出来了面向对象,让我震撼不已.本篇博客就是在此基础上加上自己的认知, ...
- swipper的一个小坑
今天闲着没事用swipper写轮播图时,发现swipper的控制不起作用,当时就很难受, 后来经过自己的仔细排查发现,用了swipper4的语法,结果引入的CSS和JS都是Swipper3版本的. 特 ...
- SAP MM ME81N PO Value Analysis报表中Net Value 为负数是怎么回事?
SAP MM ME81N PO Value Analysis报表中Net Value 为负数是怎么回事? ME81N 报表中,如下PO的net value为负数, 怎么回事? 经查这些PO都是退货采购 ...
- 简析服务端通过geotools导入SHP至PG的方法
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要在浏览器端直接上传SHP后服务端进行数据的自动入PG ...
- springboot 整合 redis
jedis 和 lettuce 都是用来连接 redis 的客户端,jedis 如果不使用连接池是非线程安全的,lettuce 使用 netty 线程安全且并发性能更好: springboot 2.x ...