“插入引发死锁”通常不是因为 INSERT 本身互斥,而是因为 插入过程中的锁行为 + 并发事务的锁等待顺序不一致 导致的。下面用最常见、最容易踩坑的场景说明。
在 InnoDB 中,INSERT 并不只是“写一行”这么简单,它可能涉及:
CREATE TABLE t (
id INT PRIMARY KEY,
code VARCHAR(20) UNIQUE
);
BEGIN;
INSERT INTO t(id, code) VALUES (1, 'A'); -- 未提交
BEGIN;
INSERT INTO t(id, code) VALUES (2, 'A'); -- 唯一冲突
此时:
code='A' 是否已存在'A',但未提交INSERT INTO t(id, code) VALUES (3, 'B');
如果此时:
➡ 互相等待 → 死锁
CREATE TABLE t (
id INT PRIMARY KEY,
age INT,
INDEX idx_age(age)
);
BEGIN;
SELECT * FROM t WHERE age = 20 FOR UPDATE;
-- 加间隙锁,防止别人插入 age=20
BEGIN;
INSERT INTO t(id, age) VALUES (10, 20);
-- 需要插入意向锁
➡ 插入被阻塞
INSERT INTO t(id, age) VALUES (11, 20);
➡ 也可能形成死锁
因为:
-- 不要在一个事务里做很多事
-- 所有事务按相同主键顺序插入
SELECT ... FOR UPDATE + INSERT 混用INSERT IGNORE / ON DUPLICATE KEY UPDATE减少唯一冲突等待
READ COMMITTED
可避免间隙锁(但语义会变)
INSERT 引发死锁,本质不是插入本身,而是:
唯一索引检查 + 间隙锁 + 插入意向锁 + 并发事务加锁顺序不同。
如果你愿意,可以把:
发出来,我可以帮你 精准定位是哪一行 SQL 导致的死锁。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。