排他锁 X | 排他意向锁 IX | 共享锁 S | 共享意向锁 IS | |
---|---|---|---|---|
排他锁 X | 冲突 | 冲突 | 冲突 | 冲突 |
排他意向锁 IX | 冲突 | 兼容 | 冲突 | 兼容 |
共享锁 S | 冲突 | 冲突 | 兼容 | 兼容 |
共享意向锁 IS | 冲突 | 兼容 | 兼容 | 兼容 |
查看事务的隔离级别:
select @@global.transaction_isolation;
避免并发操作同一个有唯一约束的值
- 若是单实例(客户端单个主机服务)内出现,可以通过go的内存锁来避免并发同一行
- 若是实例间并发,可通过redis来实现分布式锁,从而避免并发同一行
CREATE TABLE `t` (
`id` int NOT NULL,
`c` int DEFAULT NULL,
`d` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
事务一 | 事务二 | 事务三 |
---|---|---|
insert into t values(6,6,6); 持有IX锁 | ||
持有X记录锁 | insert into t values(6,6,6);(block)持IX锁,等待持有S记录锁 | |
insert into t values(6,6,6);(block)持有IX,等待持有S记录锁 | ||
begin/rollback 释放IX、X锁 | 持有S记录锁,准备升级成X锁,与事务三的S记录锁冲突 | 持有S记录锁,准备升级成X锁,与事务二的S记录锁冲突 |
deadlock |
上述的操作结果如下:一个 insert 成功,另一个死锁退出
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
参考资料