MySQL中的死锁

177 阅读2分钟

这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战

猫和老鼠.jpg

前言:
本篇文章是我关于MySQL的第9篇文章,水平一般、能力有限。文章写的比较浅,适合新手来看。本篇文章是接着前面的事务隔离级别来讲一下。

死锁

死锁的原因

死锁是指两个或两个以上的事务相互占用对方资源,并且把这些资源锁起来了。从而两个事务都不能继续执行,导致循环死锁的问题。也就是说在多个事务以不同的顺序锁定资源时就有可能发生死锁的情况。多个事务同时锁定同一资源也会有导致死锁的问题。

有点像Java代码中的死锁,两个资源互相持有对方的钥匙。

如下所示:

-- 事务1
start transaction;
update person set name='哮天犬' where id=1;
update person set sex='女' where name='哪吒';
commit;

-- 事务2
start transaction;
update person set sex='男' where name='哪吒';
update person set name='二狗子' where id=1;
commit;

死锁的解决方式

两个事务在都执行了第一条SQL时,变会锁定该行。这个时候再执行第二条SQL,发现这两行已经被锁定了。无法执行更新操作,但是这个时候两个事务都无法释放锁,也无法结束事务。就僵持住了,陷入死循环。除非有其他原因才能导致解锁。

当然数据库为了防止出现着这种情况实现了死锁的超时机制和死锁的检测。当然这个执行在复杂的存储引擎中实现的较好,在检测到循环依赖时,直接返回一个错误。这种解决方式是相当有效的,否则查询有可能会异常的慢。另外的方式就是死锁的超时机制了,在查询语句达到锁设定的超时时间时,放弃锁请求。这种方式通常来说不使用。InnoDB目前的实现方式是,将持有最少行的事务进行回滚。这种方式虽然没有那么完美,但是简单粗暴。(并不会陷入列车难题的困境中😑😑)


参考文档
《高性能MySQL》