MySQL出现死锁该怎末办?

279 阅读2分钟

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

想必从事于开发工作的各位,大家或多或少的会遇到数据库死锁的问题。我们在开发中最常使用的数据库就是MySQL数据库,本篇文章将以MySQL数据库为例,对死锁问题进行讲解。

前言

在上篇文章中我们已经对数据库的锁进行了基本的介绍,包括什么是锁,锁的级别,不同数据库引擎的锁,感兴趣的同学可以阅读一下上篇文章,本篇文章我们将直入主题,讲解MySQL死锁问题。

为什么会出现数据库死锁?

这里先介绍一下什么是死锁。

死锁就是指两个或两个以上的线程在执行过程中,因为互相抢夺资源,而造成的一种互相等待的现象。如果不通过外力干预,他们就会一直等待下去,相互耗死。

死锁的根本原因就是加锁的次序不一致。 并发才会有锁的竞争关系。

表级锁是不会出现产生死锁的,我们所遇到MySQL数据库死锁问题,一般都是InnoDB的行锁。

InnoDB的行级锁是针对索引的,如果操作没有走索引的话,InnoDB使用的则是行锁。

死锁的解决方案是什么?

  • 尽量使用较低的隔离级别。

  • 尽量使用合适的索引访问数据,使加锁更精确,从而减少锁冲突的机会。

  • 合理的选择事务的大小,小的事务引发锁冲突的概率更小。

  • 避免业务上的循环等待。

  • 并发插入时使用replace/on duplicate也可以避免死锁

  • 显式加锁时,尽量一次性请求足够级别的锁。

    比如要修改数据,最好直接申请排他锁,而不是先申请共享锁,修改时再申请排他锁,因为在此期间有可能被别的事务抢占了排他锁,导致死锁。

  • 不同的应用访问同一组表时,应尽量约定以相同的顺序访问各表。

    对一个表而言,应尽量以固定的顺序存取表中的行。这样可以减少死锁的机会。

  • 尽量使用相等的条件访问数据,这样可以避免next-key锁对并发插入的影响。

  • 不要申请超过实际需要的锁;除非必要,查询时不要加锁。

  • 对于特定的事务,可以使用表锁来提高处理速度和减少死锁的概率。