mysql 事务、死锁问题
mysql 事务、死锁问题复现:
第一个事务删除并插入,未提交;
begin; delete from t_option_value_rel_resource WHERE field_id = 1 and data_id = 1; INSERT INTO `t_option_value_rel_resource`(`id`, `field_id`, `data_id`, `business_type`, `code`) VALUES (UUID_SHORT(), 1, 1, '02', '01'); COMMIT;
第二个事务删除,等待死锁。
begin; delete from t_option_value_rel_resource WHERE field_id = 1 and data_id = 2; COMMIT;
原因:
事务1要对一个已被间隙锁控制的记录进行插入意向锁录入,遂进入阻塞等待间隙锁释放,而恰巧另一个事务也同样要对一个被间隙锁控制的记录进行插入意向锁录入,阻塞等待,当两个事务间隙锁碰巧有交集时就进入了死循环最后死锁。
意向锁:
如果对某一个节点加意向锁,就表明它的下层节点正在被加锁。
记录锁:
指where的条件中使用索引作为条件,查出来的一条数据中的索引项会加锁。
间隙锁:
记录锁中间的数据会加锁。
解决方案:
方案一:去掉事务,速度慢
可能会产生脏数据,产生脏数据的地方,再次导入可以被覆盖掉。
方案二:降低隔离级别为RC,避免间隙锁(降级后会有不可重复读和幻读问题)。
不可重复读:
如果事务A按一定条件搜索,期间事务B删除了符合条件的某一条数据,导致事务A再次读取时数据少了一条。
幻读:
事务A按照一定条件进行数据读取,期间事务B插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B新插入的数据。
方案三:设置InnoDB在RR级别下不使用间隙锁(关闭后会有幻读问题)。
innodb_locks_unsafe_for_binlog = 1
方案四:改为主键删除,主键索引只会锁住一条
随笔看心情