执行select ... where ... for update语句,锁表还是锁当前行记录

上周,我那个朋友的公司在执行一个select...where...forupdate语句时遇到了点麻烦。
他说,他们发现锁的粒度不是他们预期的,有时候是行锁,有时候却变成了表锁。
我还记得他提到了,这和事务隔离级别、查询条件以及数据库引擎的实现有关。

他说,比如,如果查询条件能用到索引,大多数情况下数据库会锁定具体的行,这样效率更高。
但如果是SERIALIZABLE隔离级别或者全表扫描,那可能就会锁定整个表。

至于死锁,他说这是有可能发生的。
他举了个例子,两个事务A和B,A想先锁行1 再锁行2 ,B想先锁行2 再锁行1 ,结果俩都卡住了,这就是死锁。

我那个朋友还提到,为了避免死锁,最好让事务按照一致的顺序访问资源,尽量减少锁的持有时间。
他还说,他现在得回去和团队讨论一下,看看怎么优化他们的查询语句。

算了,这些技术细节我也不是特别懂,你看着办吧。

select for update 并发insert死锁问题

结论: 1 . 立即放弃使用悲观锁,改用乐观锁,如使用版本号或时间戳。
2 . 如果不能放弃悲观锁,优化业务逻辑,避免多个请求同时修改同一行数据。
3 . 使用MySQL的死锁检测和解决机制,如增加死锁超时时间或重试逻辑。

具体措施:
时间:2 02 1 年7 月
地点:北京
数字:平均每月死锁1 00次
改为乐观锁:减少死锁率5 0%,减少重试次数2 0%
优化业务逻辑:减少死锁率3 0%,减少系统负载2 0%
死锁超时时间从1 0秒增加到3 0秒,重试次数从1 次增加到3 次
吐槽: 这死锁问题简直太坑了,早知道不用悲观锁了!