You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MariaDB中模拟SELECT成为死锁牺牲品的死锁场景

构造目标SELECT作为死锁牺牲品的复现方案

普通不带锁的SELECT在InnoDB默认的RC、RR隔离级别下是快照读,不申请任何行锁/间隙锁,根本不会参与锁冲突,不可能成为死锁参与方。要让你用的SELECT number, message FROM test_table WHERE number > ?被选为死锁回滚牺牲品,首先要保证这个查询会加锁:要么把数据库隔离级别设为SERIALIZABLE(普通SELECT会自动加共享next-key锁),要么查询实际是加锁读(比如业务逻辑带了FOR UPDATE/LOCK IN SHARE MODE后缀做悲观锁)。

你之前构造的场景只在两个写事务之间形成死锁,没有把目标SELECT拉进锁等待环,自然不会选中SELECT作为回滚对象。

前置准备

先在测试表插入基础数据,保证范围查询能命中记录:

TRUNCATE test_table;
INSERT INTO test_table (number, message) VALUES (1,'row1'),(50,'row2'),(100,'row3');

具体复现步骤

开3个独立的数据库连接,分别记为会话A、会话B、会话C(会话C就是跑目标SELECT的应用连接),严格按照以下顺序逐行执行,不要跳步:

  • 第一步:会话A执行,持有第一把锁
START TRANSACTION;
-- 拿到number=1行的排他X锁
SELECT * FROM test_table WHERE number = 1 FOR UPDATE;
  • 第二步:会话B执行,持有第二把锁
START TRANSACTION;
-- 拿到number>50范围的排他next-key锁,覆盖50到正无穷的区间和间隙
SELECT * FROM test_table WHERE number > 50 FOR UPDATE;
  • 第三步:会话A执行,进入等待
-- 尝试插入number=60的行,该位置落在会话B持有的>50锁范围内,会被阻塞,等待B释放锁
INSERT INTO test_table (number, message) VALUES (60, 'insert from A');
  • 第四步:会话C(你的应用连接)执行目标查询,进入等待
START TRANSACTION;
-- 执行你的目标查询,非SERIALIZABLE隔离级别下加LOCK IN SHARE MODE模拟加锁场景
-- 该查询需要拿number>1范围的共享锁,number=1的锁被A持有、number>50的锁被B持有,直接进入等待队列
SELECT number, message FROM test_table WHERE number > 1 LOCK IN SHARE MODE;
  • 第五步:会话B执行,触发死锁闭环
-- 尝试更新number=1的行,需要拿该行的X锁
-- 此时number=1的锁等待队列顺序为:A(持有锁)→ C(等共享锁)→ B(等排他锁),B必须等C释放锁才能拿到权限
-- 等待环正式形成:A等B → B等C → C等A,三事务死锁
UPDATE test_table SET message = 'update from B' WHERE number = 1;

结果说明

死锁检测触发后,InnoDB会根据事务的undo日志量、修改行数计算权重,选择权重最低的事务回滚。三个事务里,会话C只执行了一个SELECT查询,没有任何数据修改,权重最低,会被直接选为死锁牺牲品,你的应用会收到Deadlock found when trying to get lock; try restarting transaction的报错。
执行SHOW ENGINE INNODB STATUS查看最新死锁日志,可以明确看到被回滚的事务就是执行目标SELECT的会话C。

注意事项

  • 如果复现失败,先检查目标SELECT是不是真的加了锁:普通快照读不会进等待队列,永远不会成为死锁参与方
  • 步骤顺序不能乱,必须保证会话C的SELECT在会话B执行最后一步UPDATE之前进入等待队列,否则锁环不会覆盖C
  • 不需要特意加SLEEP,按顺序逐行执行即可,每一步的阻塞是数据库锁机制保证的

内容的提问来源于stack exchange,提问作者user14073111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 10:36:24