• 记一次Mysql并发死锁


    数据准备

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

    session参数设置

    1. //手动提交
    2. set session autocommit=0;

    模拟并发

    session1

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

    session2

    1. start TRANSACTION;
    2. INSERT INTO t(cell) VALUES('5555555');
    3. 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列建立索引

  • 相关阅读:
    C专家编程 第1章 C:穿越时空的迷雾 1.11 轻松一下---由编译器定义的Pragmas效果
    【深度学习入门】- 用电路思想解释感知机
    SpringBoot项目如何优雅的实现操作日志记录
    Hive实践——将查询的数据按照分区进行存储
    win10-如何管理开机启动项?
    阿里 OSS鉴权访问文件
    华为od德科面试数据算法解析 2022-8-3 消息队列合并
    STM32的寄存器深度解析
    数据库概念介绍
    第一章 - Windows安装VMware Workstation Pro
  • 原文地址:https://blog.csdn.net/weixin_35973945/article/details/126484242