前言
在上篇文章中我们已经对数据库的锁进行了基本的介绍,包括什么是锁,锁的级别,不同数据库引擎的锁,感兴趣的同学可以阅读一下上篇文章,本篇文章我们将直入主题,讲解MySQL死锁问题。
为什么会出现数据库死锁?
这里先介绍一下什么是死锁。
死锁就是指两个或两个以上的线程在执行过程中,因为互相抢夺资源,而造成的一种互相等待的现象。如果不通过外力干预,他们就会一直等待下去,相互耗死。
死锁的根本原因就是加锁的次序不一致。 并发才会有锁的竞争关系。
表级锁是不会出现产生死锁的,我们所遇到MySQL数据库死锁问题,一般都是InnoDB的行锁。
InnoDB的行级锁是针对索引的,如果操作没有走索引的话,InnoDB使用的则是行锁。
死锁的解决方案是什么?
- 尽量使用较低的隔离级别。
- 尽量使用合适的索引访问数据,使加锁更精确,从而减少锁冲突的机会。
- 合理的选择事务的大小,小的事务引发锁冲突的概率更小。
- 避免业务上的循环等待。
- 并发插入时使用replace/on duplicate也可以避免死锁
- 显式加锁时,尽量一次性请求足够级别的锁。
比如要修改数据,最好直接申请排他锁,而不是先申请共享锁,修改时再申请排他锁,因为在此期间有可能被别的事务抢占了排他锁,导致死锁。
- 不同的应用访问同一组表时,应尽量约定以相同的顺序访问各表。
对一个表而言,应尽量以固定的顺序存取表中的行。这样可以减少死锁的机会。
- 尽量使用相等的条件访问数据,这样可以避免next-key锁对并发插入的影响。
- 不要申请超过实际需要的锁;除非必要,查询时不要加锁。
- 对于特定的事务,可以使用表锁来提高处理速度和减少死锁的概率。