数据库死锁原因以及解决

有一篇讲了mvcc的基本原理:https://www.cnblogs.com/benjerry/p/17551031.html

这样就知道最简单的死锁产生原因,就是有两个并发事务,事务1先更新a表某行数据,再更新b表某行数据,事务2先更新b表同行数据,再更新a表同行数据,就非常有可能死锁了。这种易检测的死锁通常会被自动释放。

还有种写法,select for update,将共享锁上升到独占锁,也可能死锁。

自增主键,多线程批量插入,这种就检测不到。 

 

先谈谈如果我们开启事务更新多表的时候的注意事项:

第一点,就是开启事务操作多表尽量不要批量操作数据

第二点,对于相同表的操作尽量顺序一致,不要事务1更新ab,事务2更新ba

第三点,事实上很多时候可以从需求上和代码逻辑上缓和这种事务上的多表操作,

比如代码上,我就不开事务操作多表,因为通常来说代码足够稳定,逻辑写的足够好,不开事务也是可以正确执行的,直接用事务包裹实际上是一种为了数据安全的暴力操作,是下策;我完全可以在程序出错时,多写几条数据恢复的sql执行。

再说需求上,如果我们的目的是希望数据安全能被兜底,那也完全可以提示用户数据出错,希望他手动删除脏数据。

第四点,别用自增主键做多线程批量插入

 

解决方法

 查询到死锁线程kill掉

第二种,尝试手动rollback事务并重新执行

第三种,用java的锁或者分布式锁让两个事务互斥执行,但是不太好,代码入侵太高

第四种,用队列让两个事务排队执行

第五点,是对第二点的衍生,通过代码把等待事务超时回滚掉,我还没找到现成方案,但是应该可行,而且比较优雅。但是这么搞就需要完备的设计方案了,包括记录日志,超时回滚原因,最好能找到框架

posted @ 2023-07-16 13:27  时间羚羊  阅读(346)  评论(0编辑  收藏  举报