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未提交事务导致锁竞争。

通过查询锁信息并终止阻塞事务可解决死锁,步骤如下:
执行 select * from information_schema.innodb_lock_waits;,查看阻塞与被阻塞事务的ID及资源。
注意:仅当阻塞发生时可查询到记录,超时后记录消失。

执行 select * from information_schema.innodb_trx;,获取死锁事务的 trx_mysql_thread_id(即会话ID)。
执行 kill [sessionId];(如 kill 15;)终止问题会话。
再次查询 innodb_trx 确认无锁事务记录,即死锁已解决。
通过规范操作顺序和优化SQL可预防死锁,具体措施如下:
操作顺序一致
多表操作时按固定顺序处理(如先操作表A再操作表B),避免交叉锁定资源。
使用唯一索引
所有 UPDATE 和 DELETE 操作必须通过唯一索引定位数据,减少锁范围。
优化SQL查询
避免复杂多表关联查询,使用执行计划分析SQL,为全表扫描语句添加索引。
调整语句顺序
将 SELECT 查询放在 UPDATE 前,先获取数据再修改,减少锁持有时间。
减少事务交互
避免事务中等待用户输入,确保事务尽可能短且自动化。
总结:死锁是并发控制的副作用,通过理解其产生场景、掌握解决工具(如锁等待查询和会话终止)及遵循预防策略(如顺序操作和索引优化),可有效降低死锁风险并提升数据库稳定性。