• 【mysql官方文档】死锁


    A deadlock is a situation where different transactions are unable to proceed because each holds a lock that the other needs. Because both transactions are waiting for a resource to become available, neither ever release the locks it holds.

    死锁是这样产生的:不同的事务都持有对方所需要的锁,并同时等待对方释放锁。

    一个select ··· lock in share mode与delete的死锁实例

    创建一个表,并插入数据:

    1. mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
    2. Query OK, 0 rows affected (1.07 sec)
    3. mysql> INSERT INTO t (i) VALUES(1);
    4. Query OK, 1 row affected (0.09 sec)

    事务A事务B结果
    select * from t where i = 1 lock in share mode;获取到S锁
    delete from t where i = 1;试图获取X锁, 因事务A持有该行的读锁,因此进入锁等待队列。
    delete from t where i = 1;死锁产生,此处事务A试图获取一个写锁,但是事务B在等待队列的前面,事务A无法将读锁升级为写锁。A等待B释放写锁,B等待A释放读锁。

    当update、select for update按照不同的顺序锁定了不同的表,就容易发生死锁。

     在同一张表中,两个事务按不同顺序分别锁定不同的记录或间隙,也会死锁。

    InnoDB使用自动行级锁定。即使在只insert或delete一行的事务中,也可能出现死锁。这是因为这些操作不是真正的“原子”;它们会自动对插入或删除的行的(可能有多个)索引记录设置锁。

     

    如何避免死锁

    1. 事务比LOCK TABLE会好一些

    2. 事务尽可能小,避免读写大量数据

    3. 不同事务尽可能按照相同的顺序获取锁(select for update)

    4. 在select for update 和 update where 上创建索引

    5. 死锁出现的可能性与事务的隔离级别没有关系,死锁与写操作有关,隔离级别解决的是读取的可见性

    6. SHOW ENGINE INNODB STATUS 可以查看死锁的原因。

    7. 频繁出现死锁时,使能innodb_print_all_deadlocks

    8. 使用select for update , select lock in share mode,建议隔离级别为RC

    9. 操作多张表,或者同一张表的不同行时,建议使用相同的顺序,可以避免死锁的产生

    10. 设置合适的索引,避免扫描大量的数据行

    11. 尽可能使用一般select而不是for update,避免锁定

    12. 串行化是最终方案

  • 相关阅读:
    Ruoyi从mysql切换到postgresql的几个坑
    el-select下拉多选框 el-select 设置默认值不可删除功能
    普通空调实现远程控制基础知识解读
    P8813 [CSP-J 2022] 乘方
    nginx-QPS限制
    万宾科技智能井盖的效果怎么样?
    分布式.RPC-WebService Restful风格实现
    LeetCode HOT 100 —— 48.旋转图像
    如何在 MAC 电脑上查找 IP 地址
    架构师spring boot 面试题
  • 原文地址:https://blog.csdn.net/Day_and_Night_2017/article/details/125571028