1、什么是死锁
会话A持有一行数据的锁,会话B持有另一行数据的锁。 A申请获取B持有的那个锁,但是被B占用着,所以A等待。 B申请获取A持有的那个锁,但是被A占用着,所以B等待。
2、死锁的本质
两个或多个会话/线程,本身拥有一个锁,但是去互相申请对方拥有的锁,导致都在锁等待,即为死锁。索引失效会造成表锁,比死锁更严重
3、举例
在RR隔离级别下,数据库有两条数据id=1和id=10。 且id为普通索引 两个事务,事务 1: select * from table where id=3 for update。 insert (id=3),他会在(1,3) (3,10)之间加间隙锁,在(3)这个位置申请插入意向锁。 事务2: select * from table where id=5 for update, insert(id=5)。 它会在(1,5) (5,10)之间加间隙锁,由于间隙锁互相兼容,故该锁可以获取,另外在(5)这个地方申请插入意向锁。 当事务1要获取插入意向锁时,发现(3)被事务2的间隙锁锁住了,故等待事务2释放锁; 事务2要获取插入意向锁时,发现(5)被事务1的间隙锁锁住了,故等待事务1释放锁;——死锁形成
4、InnoDB的死锁检测
InnoDB内部会自动识别死锁,并回滚其中一个权重较小的事务。一般为修改量最小的,undo log最小的。
5、避免死锁
①、注意sql的执行顺序,尽量让sql以相同顺序获取数据,
②、大事务化为小事务,减少持有锁的时间,
③、加快sql执行速度,优化sql,包括建立索引,
④、优化表结构,可一定程度上避免死锁
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !