锁种类
- 插入意向锁(insert intention lock)
- 对已有数据行的修改与删除,必须加强互斥锁 X 锁,那对于数据的插入,是否还需要加这么强的锁,来实施互斥呢?插入意向锁,孕育而生。
- 插入意向锁是间隙锁(Gap Locks)的一种,它是专门针对 insert 操作的,也是为数不多的在 RC 级别下产生 Gap 锁情况
锁兼容性
排他锁 X | 排他意向锁 IX | 共享锁 S | 共享意向锁 IS | |
---|---|---|---|---|
排他锁 X | 冲突 | 冲突 | 冲突 | 冲突 |
排他意向锁 IX | 冲突 | 兼容 | 冲突 | 兼容 |
共享锁 S | 冲突 | 冲突 | 兼容 | 兼容 |
共享意向锁 IS | 冲突 | 兼容 | 兼容 | 兼容 |
查看事务的隔离级别:
select @@global.transaction_isolation;
避免并发操作同一个有唯一约束的值
- 若是单实例(客户端单个主机服务)内出现,可以通过go的内存锁来避免并发同一行
- 若是实例间并发,可通过redis来实现分布式锁,从而避免并发同一行
三个并发导致insert
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 成功,另一个死锁退出
操作如下
事务1 :
事务2:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
事务3:
结果
参考资料
- https://blog.csdn.net/sinat_41780498/article/details/111995067