记一次Mysql并发死锁

数据准备

create table t
(
    id   int(20) auto_increment
        primary key,
    cell varchar(20) null
);
INSERT INTO t (id, cell) VALUES (1, '11111111111');
INSERT INTO t (id, cell) VALUES (2, '22222222222');
INSERT INTO t (id, cell) VALUES (3, '33333333333');
INSERT INTO t (id, cell) VALUES (4, '44444444444');
INSERT INTO t (id, cell) VALUES (5, '55555555555');

session参数设置

//手动提交
set session autocommit=0;

模拟并发

session1

start TRANSACTION;
INSERT INTO t(cell) VALUES('44444444');
UPDATE t set cell = 123 WHERE cell = '44444444' ;

session2

start TRANSACTION;
INSERT INTO t(cell) VALUES('5555555');
UPDATE t set cell= 456 WHERE cell = '5555555' ;

多个终端session模拟并发事务

时间序号session1session2
1start TRANSACTION;
2INSERT INTO t(cell) VALUES('44444444');
3
start TRANSACTION;
4
INSERT INTO t(cell) VALUES('5555555');
5
UPDATE t set cell = 123 WHERE cell = '44444444' ;
6
UPDATE t set cell= 456 WHERE cell = '5555555' ;

结果

  • 当运行到事务1的update时,发生了等待
  • 当运行到事务2的update时,发生了死锁

问题分析

根据show engine innodb status查询 

 可见Transaction1与Transaction2 同时锁住了同一部分,而且是locak_mode X rec bur not gap Record lock

事务1的insert产生了一个插入意向锁(insert 会对插入的这条记录加排他记录锁,在加记录锁之前还会加一种 GAP 锁,叫做插入意向锁),事务2的insert也产生了一个插入意向锁(不会被互相锁住,因为数据行并不冲突),此时事务1再进行update语句,因未走索引,导致扫全表,而在扫到事务2插入那条数据时,行锁与插入意向锁冲突了,导致事务1需要等待事务2释放插入意向锁而进行等待。事务2在进行update时,也同样需要扫全表,但是全表都被事务1的update锁住了,事务2需要等待 等待事务2释放插入意向锁的 事务1 的行锁 释放,因此发生了死锁

解决方法:在cell列建立索引

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值