看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法

有没有人在啊,想请说明下,看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法
最新回答
冬瑾凉桉

2026-10-21 13:31:50

死锁是数据库并发访问时,两个或多个事务互相等待对方释放资源而陷入无限等待的状态。以下从死锁产生场景、解决方法及避免策略展开详细说明:

一、死锁产生的场景

死锁通常发生在多个事务以不同顺序竞争相同资源时,具体场景如下:

  • 场景演示

    创建测试环境

    创建数据库 chuanzhi,选择该库后创建表 tb_heima(含主键 id 和字段 username),并插入初始数据。

    代码示例:

    create database chuanzhi;use chuanzhi;CREATE TABLE `tb_heima` (`id` INT NOT NULL, `username` VARCHAR(45) NULL, PRIMARY KEY (`id`));INSERT INTO `tb_heima` (`id`, `username`) VALUES ('1', '传智教育-教育行业A股IPO第一股');

    模拟死锁过程

    窗口1:开启事务后执行更新语句(未提交),持有 id=1 的写锁。

    begin;update tb_heima set username = 'heima' where id =1;

    窗口2:开启另一个事务并执行相同更新语句,因窗口1未释放锁而阻塞。

    begin;update tb_heima set username = 'heima' where id =1;

    结果:窗口2等待超时后报错,因窗口1未提交事务导致锁竞争。

二、解决死锁问题

通过查询锁信息并终止阻塞事务可解决死锁,步骤如下:

  1. 查询锁等待信息

    执行 select * from information_schema.innodb_lock_waits;,查看阻塞与被阻塞事务的ID及资源。

    注意:仅当阻塞发生时可查询到记录,超时后记录消失。

  1. 查询事务状态

    执行 select * from information_schema.innodb_trx;,获取死锁事务的 trx_mysql_thread_id(即会话ID)。

  1. 终止阻塞会话

    执行 kill [sessionId];(如 kill 15;)终止问题会话。

    再次查询 innodb_trx 确认无锁事务记录,即死锁已解决。

三、避免死锁的策略

通过规范操作顺序和优化SQL可预防死锁,具体措施如下:

  • 操作顺序一致

    多表操作时按固定顺序处理(如先操作表A再操作表B),避免交叉锁定资源。

  • 使用唯一索引

    所有 UPDATE 和 DELETE 操作必须通过唯一索引定位数据,减少锁范围。

  • 优化SQL查询

    避免复杂多表关联查询,使用执行计划分析SQL,为全表扫描语句添加索引。

  • 调整语句顺序

    将 SELECT 查询放在 UPDATE 前,先获取数据再修改,减少锁持有时间。

  • 减少事务交互

    避免事务中等待用户输入,确保事务尽可能短且自动化。

总结:死锁是并发控制的副作用,通过理解其产生场景、掌握解决工具(如锁等待查询和会话终止)及遵循预防策略(如顺序操作和索引优化),可有效降低死锁风险并提升数据库稳定性。