InnoDB 引擎相比于 MyISAM 引擎,有一个优点就是 InnoDB 引擎支持行锁,而 MyISAM 引擎在做并发控制时只能使用表锁,这篇文章学习一下 InnoDB 引擎中死锁是如何产生的。
1.笔记图
2.行锁说明
- 行锁就是针对数据表中行记录的锁
- MySQL 行锁是在引擎层自己实现的
- InnoDB 支持行锁,MyISAM 引擎不支持行锁,这也是 MyISAM 和 InnoDB 区别之一
3.两阶段锁协议
Tips:事务 B 的 update 语句会被阻塞,直到事务 A 执行 commit 之后,事务 B 才能继续执行。
- 在 InnoDB 事务中,行锁是在需要的时候才加上的,要等到事务结束时才释放,这个就是两阶段锁协议
- 如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放,可以最大程度地减少了事务之间的锁等待,提升了并发度
4.死锁和死锁检测
- 死锁:
- 并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁
- 事务 A 在等待事务 B 释放 id=2 的行锁,而事务 B 在等待事务 A 释放 id=1 的行锁
- 事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态
- 死锁检测:
- innodb_deadlock_detect:默认是 on
- 并发场景每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,要消耗大量的 CPU 资源,但是每秒执行的事务数很少
5.死锁检测优化思路
- 如果能确保业务一定不会出现死锁,可以临时把死锁检测关掉
- 数据库服务端做并发控制,可以考虑在中间件实现,也可以修改 MySQL 源码在数据进入引擎之前排队,这样在 InnoDB 中就不会有大量的死锁检测消耗 CPU 了