SQLite数据库锁问题

记得以前设计评审时,想用SQLite数据库实现某个功能,被教导说应该用Postgresql数据库,因为Postgresql数据库是行锁,而SQLite的锁粒度太粗了。当时还没有什么感觉。

后来在另一个产品的群里面,经常看到其中的开发和测试说SQLite数据库死锁了。这才留了一下心。

最近又要使用它,于是拜读了下《SQLite权威指南》,里面赫赫一句话:SQLite处理并发读没有什么问题,但是如果你的应用需要并发写的话,那么SQLite就不适合你了。

看了一下SQLite数据库的锁机制:

它包括四种锁,共享锁(Shared lock)、预留锁(Reserved lock)和未决锁(Pending lock)、排他锁(Exclusive lock)

其中读操作,用的是Shared lock,所以并发的多个读数据库。如果有一个读操作存在,那么都不会允许写。

而写就比较麻烦,

1.它首先会申请一个预留锁(Reserved lock),在启用Reserved lock之后,已存在的读可以继续读,也可以有新的读请求。

2.然后,它会把需要更新的数据写到缓冲区中。

3.需要写到缓冲区的更新写完以后,就需要将更新刷到硬盘db了。这时,它会申请Pending lock,就不能再有新的Shared lock申请了,也就是阻止了新的读操作。但是已经存在的读操作还是可以继续读的。然后它就等待,直到没有读操作存在(即所有的读都已经结束)这个时候,它就会申请排他锁,此时不允许有其他锁的存在,然后进行commit,将缓冲区的数据写入db中。

书上给举了个例子:

B进行写操作,申请了预留锁;然后A进行读操作,申请了共享锁(有预留锁时,是允许读操作申请的);然后A又同时想进行写操作(未释放共享锁的情况),此时申请预留锁(因为已经有预留锁存在了)失败;B写完缓存,想commit时,申请了未决锁,但是无法从未决锁提升到排他锁(因为有共享锁存在)。此时,发生死锁,A和B都想等待对方释放锁。


对应一下自己的场景:

1.页面有多个读

2.后台会定时写

按照书上说的,写锁的时长大概是几毫秒。我写程序也尽量注意了。也许在极端情况下,在写时,恰好有读锁未释放,不过几毫秒内,概率不算很大。

另外,就算是这种极端情况未写成功,在下一个5分钟写时,也会把上一个5分钟未commit的给补救上去。从前台看来,就是数据会有一定时延。


另外一个隐含的需求:页面可能也需要进行更新数据的操作,这个写是有用户的某个动作触发的,那么在多用户的情况下,读写同时、写写同时的概率就会很大。对此,希望是采取规避的方式,在后台提供与此更新操作的脚本,而非在前台页面提供。


由此可见,SQLite作为一个嵌入式数据库,不太适合用在高并发的场景下;另外,以上都是理论,希望有时间阅读源码,能够彻底弄清楚一切。

讨论了下,为了规避风险,还是不用SQLite了。什么时候,SQLite才能把数据库级别的锁改为行锁?不过如果真的SQLite支持行锁,那么就违背它轻量、简单的初衷了。所以,这个终究是一个梦。


  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值