高性能MySQL

MySQL中的锁5-死锁

2018-08-11  本文已影响2人  Coding小聪

什么是死锁

在程序执行过程中,有两个或两个以上的事务因为争夺锁资源而造成的一种相互等待的现象。例如:事务t1和事务t2在执行过程中都需要获取锁A和锁B,实际运行过程有可能会是t1获取到锁A等待获取锁B,与此同时,t2已经获取到锁B且等待获取锁A。这时事务t1和事务t2都想获取对方持有的锁,而它们已经获取的锁在事务未执行完又不能释放。所以此时死锁就产生了,这也是常见的AB-BA死锁。下面演示一下这个死锁:

会话1
会话2

MySQL中通过wait-for graph会自动检测出是否产生了死锁。
当检测到发生了死锁时,MySQL会自动回滚。而发送错误(非死锁),事务会中止不会自动回滚,需要手动回滚或提交。

解决死锁

我们可以通过锁超时来解决死锁问题,在InnoDB可以通过innodb_lock_timeout变量来设置锁的超时时间。

典型的死锁案例剖析

一、购物车死锁

环境说明
• 用户1 的购物车:
1. product_id= 100 的商品
2. product_id= 110 的商品
3. product_id= 10 的商品
• 用户2 的购物车:
1. product_id= 10 的商品
2. product_id= 110 的商品
3. product_id= 100 的商品
1. 当一个商品被购买时,其中有一个环节是 库存减1 ,即做update操作( set stock=stock-1 where product_id=xx)
2. 当两个用户购买的产品的 product_id 顺序交叉,且两个用户同时下订单时,购物车中的每个商品都会执行 库存减1 的操作,即 每个用户 在各自的 一个事物 中做 三次update 操作,此时即发生了 死锁 (类似AB-BA死锁)

解决办法
在应用程序端进行修改,即提交购物车订单时,对 订单进行排序 ,然后再执行提交。这样只会出现锁等待,而不会出现死锁

MySQL中存在很多非常复杂的产生死锁的情况,但是产生原因都是一样的,后续实际工作中遇到再进行补充吧。

上一篇 下一篇

猜你喜欢

热点阅读