弃用悲观锁

简介: 【8月更文挑战第4天】

从理论上来说,解决方案有三种:

  • 不管有没有数据,先插入一个默认的数据。如果没有数据,那么会插入成功;如果有数据,会出现主键冲突或唯一索引冲突,插入失败。在插入成功的时候,执行以前数据不存在的逻辑,因为此时数据库里有数据,所以不会使用间隙锁,而是使用行锁,从而规避了死锁问题。
  • 调整数据库的隔离级别,降低为已提交读就没有间隙锁了。可以进一步把话题引申到MVCC中。
  • 放弃悲观锁,使用乐观锁。这也是亮点方案。

可以通过一个案例说明,关键词是临键锁。

早期优化过一个死锁问题,是临键锁引起的,业务逻辑很简单,先用 SELECT FOR UPDATE 查询数据。如果查询到了数据,那么就执行一段业务逻辑,然后更新结果;如果没有查询到,那么就执行另外一段业务逻辑,然后插入计算结果。
那么如果 SELECT FOR UPDATE 查找的数据不存在,那么数据库会使用一个临键锁。此时,如果有两个线程加了临键锁,然后又希望插入计算结果,那么就会造成死锁。
我这个优化也很简单,就是上来先不管三七二十一,直接插入数据。如果插入成功,那么就执行没有数据的逻辑,此时不会再持有临键锁,而是持有了行锁。如果插入不成功,那么就执行有数据的业务逻辑。
此外,还有两个思路。一个是修改数据库的隔离级别为 RC,那么自然不存在临键锁了,但是这个修改影响太大,被 DBA 否决了。另外一个思路就是使用乐观锁,不过代码改起来要更加复杂,所以就没有使用。

后续可能会追问隔离级别的事情,或是问乐观锁的细节。

很多人为了省事会直接使用悲观锁,比如事务里存在SELECT ... FOR UPDATE的语句,而后面紧跟一个UPDATE语句

// 开启事务
Begin()
// 查询到已有的数据 SELECT * FROM xxx WHERE id = 1 FOR UPDATE
data := SelectForUpdate(id) 
newData := calculate(data) // 一大通计算

// 将新数据写回去数据库 UPDATE xxx SET data = newData WHERE id =1
Update(id, newData) 
Commit()

考虑这一类代码直接把事务给去掉,纯粹依赖CAS操作

for {
  // 查询到已有的数据 SELECT * FROM xxx WHERE id = 1
  data := Select(id) 
  newData := calculate(data) // 一大通计算

  // 将新数据写回去数据库 
  // UPDATE xxx SET data = newData WHERE id =1 AND data=oldData
  success := CAS(id, newData, data) 
  // 确实更新成功,代表在业务执行过程中没有人修改过这个 data。
  // 适合读多写少的情况
  if success {
    break;
  }
}

这里是直接用data来比较的,实践中也可能引入version列,或是update_time来确保数据没有发生更改。
可以聊到乐观锁的情况下,用这个案例。

目录
相关文章
|
存储 关系型数据库 MySQL
MVCC多版本并发控制
MVCC多版本并发控制 1、MVCC MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
103 0
|
2月前
|
算法 Java 关系型数据库
何为乐观锁和悲观锁
何为乐观锁和悲观锁
|
4月前
|
数据库 开发者
使用版本号实现乐观锁
使用版本号实现乐观锁
|
算法
悲观锁和乐观锁的区别
悲观锁和乐观锁的区别
233 0
|
数据库
乐观锁和悲观锁的底层原理
乐观锁和悲观锁是并发编程中常用的两种锁机制,用于解决多线程或多进程环境下的并发访问问题。它们的底层原理和适用场景有所不同。
156 0
|
存储 关系型数据库 MySQL
【MySQL】MVCC多版本并发控制(重点:MVCC实现原理之ReadView)
本文重点介绍MySQL的MVCC概念、快照读与当前读、MVCC实现原理之ReadView、隐藏字段、Undo Log版本链。
402 0
|
存储 关系型数据库 MySQL
多版本并发控制MVCC
多版本并发控制MVCC
多版本并发控制MVCC
|
数据采集 算法 Java
锁住它,快告诉我乐观锁与悲观锁的区别?
锁住它,快告诉我乐观锁与悲观锁的区别?
148 1
锁住它,快告诉我乐观锁与悲观锁的区别?
|
SQL 关系型数据库 MySQL
事务丢失更新问题及乐观锁、悲观锁机制
事务丢失更新问题及乐观锁、悲观锁机制
292 0
事务丢失更新问题及乐观锁、悲观锁机制
|
存储 关系型数据库 MySQL
多版本并发控制 MVCC
本篇文章主要介绍了 多版本并发控制(MVCC)在 MySQL 的实现
198 0

热门文章

最新文章