前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >真实线上问题之数据库死锁如何解决?

真实线上问题之数据库死锁如何解决?

原创
作者头像
@派大星
发布2024-06-24 09:34:40
1030
发布2024-06-24 09:34:40
举报
文章被收录于专栏:MySQLMySQL

数据库死锁是指在多个并发事务中,彼此之间发生相互等待的情况,导致所有事务都无法继续执行的情形。

关于死锁的概念之前有提到过,可参考文章:

对线面试官 - MySQL 隔离级别 、锁机制

数据库死锁通常由以下原因导致:

  1. 资源竞争:多个事务试图同时访问相同的资源,如数据库表、行、页或锁,但它们请求资源的顺序不同,导致相互等待。
  2. 未释放资源:事务在使用完资源后未及时释放,导致其他事务无法获得所需的资源。这可能是由于程序错误或异常情况引起的。
  3. 不同事务执行速度不同:某些事务执行速度较慢,持有资源的时间过长,其他事务需要等待释放,可能导致死锁。
  4. 操作数据量过大:事务在持有锁的同时,又请求获取更多的锁,导致互相等待。

解决(避免)死锁的方法包括:

  1. 减少锁的数量:使用更低级别的隔离级别如读提交(Read Committed),而非重复读(Repeatable Read),可以避免特定类型的锁竞争。
  2. 缩短事务持有锁的时间:优化事务处理逻辑,减少事务执行时间,降低发生死锁的可能性。
  3. 确定访问数据的固定顺序:在访问多个资源时,保持一致的访问顺序,以减少死锁的发生。
  4. 降低操作数据的量:减少事务需要操作的数据量,尽可能缩短事务的持有时间,以减少死锁的风险。

这些方法可以有效预防和解决数据库死锁问题,提升系统的并发处理能力和稳定性。

MySQL 只操作同一条记录,也会发生死锁吗?

答案是肯定会的。

因为数据库的锁机制针对的是索引而非记录本身。

在事务中,当我们更新一条记录时,如果使用普通索引作为条件,数据库会先获取普通索引的锁,然后尝试获取主键索引的锁。

若此时有另一个线程已经获得了该记录的主键索引锁,并且同时在其事务中试图获取该记录的普通索引锁,就可能导致死锁的发生。

代码语言:sql
复制
update my_table set name = 'paidaxing',age = 22 where name = "paidaxingwang";

这个SQL会先对name加锁, 然后再回表对id加锁。

-----

select * from my_table where id = 15 for update;

update my_table set age = 33 where name like "paidaxing%";

-- 以上SQL,会先获取主键的锁,然后再获取name的锁。

为了预防这种死锁情况,可以在应用程序中设定特定的索引获取顺序规则,比如规定只能按照主键索引 -> 普通索引的顺序获取锁。这样可以确保不同线程在获取锁时遵循统一的顺序,从而有效地避免死锁的发生(通过 SQL 保证)。

什么是死锁,如何解决?

死锁是指两个或两个以上的进程(或线程)在执行过程中,由于竞争资源或者彼此通信而造成的一种阻塞现象。在无外力作用下,它们都无法继续向前推进。这种状态被称为系统处于死锁状态,或者简称系统发生了死锁。这些相互等待的进程被称为死锁进程。

比如,丈母娘要求先买房才能结婚,但女婿坚持要先结婚再买房,这种情况类比了死锁的概念。

发生死锁的四个必要条件是:

  1. 互斥条件:一个资源每次只能被一个进程或线程使用。
  2. 占有且等待:一个进程因请求资源而阻塞时,继续持有已获得的资源。
  3. 不可抢占:已获得的资源在未使用完之前不可被强行剥夺。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

解除死锁可以从以下几个方面入手:

  • 破坏不可抢占条件:设置资源的优先级,允许高优先级的进程可以抢占低优先级进程的资源。
  • 破坏循环等待条件:保证所有进程(线程)请求资源的顺序是一致的,比如按照固定的顺序请求资源,例如 A->B->C,避免形成循环等待。

在数据库中,如果多个事务并发执行,也可能会发生死锁。例如,当事务 1 持有资源 A 的锁,尝试获取资源 B 的锁,同时事务 2 持有资源 B 的锁,尝试获取资源 A 的锁时,就可能导致死锁的发生。

发生死锁时,可能会出现如下异常情况:

代码语言:plsql
复制
Error updating database. Cause: ERR-CODE: [TDDL-4614][ERR_EXECUTE_ON_MYSQL]

Deadlock found when trying to get lock;

一般来说,对于数据库的死锁问题,主要是要避免并发修改的冲突。另外一种方法是保证操作的顺序,例如多个事务都先操作资源 A,再操作资源 B,这样可以有效地避免死锁的发生。

如何排查死锁问题?您在生产环境中是否遇到过?逐步的排查方法是什么?感兴趣的小伙伴可以点赞收藏,下期出。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MySQL 只操作同一条记录,也会发生死锁吗?
  • 什么是死锁,如何解决?
    • 发生死锁的四个必要条件是:
      • 解除死锁可以从以下几个方面入手:
      相关产品与服务
      云数据库 MySQL
      腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档