• MySQL--死锁的原因及解决方法


    原文网址:MySQL--死锁的原因及解决方法_IT利刃出鞘的博客-CSDN博客

    简介

    说明

    本文介绍MySQL死锁的原因及解决方法。

    InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,所以可能发生死锁

    不会死锁的情况

    MyISAM表不会出现死锁(Deadlock Free) 。

    原因:用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,并且MySQL不支持锁升级。也就是说,在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。其实,在自动加锁的情况下也基本如此,MyISAM总是一次获得SQL语句所需要的全部锁。

    导致死锁的场景

    先申请共享锁后申请排它锁(同一张表)

    在事务中,更新记录时应该直接申请足够级别的锁,即排他锁,而不应先申请共享锁,更新时再申请排他锁。因为当申请排他锁时,其他事务可能又已经获得了相同记录的共享锁,从而造成锁冲突,甚至死锁。

    下面的例子中,先申请共享锁,更新时再申请排他锁,造成死锁。

    session_1session_2

    mysql> set autocommit = 0;

    Query OK, 0 rows affected (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE    |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    mysql> set autocommit = 0;

    Query OK, 0 rows affected (0.00 sec)

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE    |

    +----------+------------+-----------+

    1 row in set (0.00 sec)

    当前session对actor_id=178的记录加共享锁:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 lock in share mode;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE    |

    +----------+------------+-----------+

    1 row in set (0.01 sec)

    其他session仍然可以查询记录,并也可以对该记录加共享锁:

    mysql> select actor_id,first_name,last_name from actor where actor_id = 178 lock in share mode;

    +----------+------------+-----------+

    | actor_id | first_name | last_name |

    +----------+------------+-----------+

    | 178      | LISA       | MONROE    |

    +----------+------------+-----------+

    1 row in set (0.01 sec)

    当前session对锁定的记录进行更新操作,等待锁:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    等待

    其他session也对该记录进行更新操作,则会导致死锁退出:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    获得锁后,可以成功更新:

    mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

    Query OK, 1 row affected (17.67 sec)

    Rows matched: 1  Changed: 1  Warnings: 0

    访问两个表的顺序不同

    如果不同的程序会并发存取多个表,应尽量约定以相同的顺序来访问表,这样可以大大降低产生死锁的机会。

    下面的例子中,由于两个session访问两个表的顺序不同,发生死锁的机会就非常高!但如果以相同的顺序来访问,死锁就可以避免。

    上边只是部分内容,为便于维护,本文已迁移到此地址:MySQL-死锁的原因及解决方法 - 自学精灵

  • 相关阅读:
    使用Node.js手撸一个建静态Web服务器,内部CV指南
    DELETE、TRUNCATE 和 DROP 在MySQL中的区别及使用示例
    老卫带你学---leetcode刷题(344. 反转字符串)
    关于是我的精灵问题还是代码还是动画的问题!
    理论第十一课——字符串
    从NLP视角看电视剧《狂飙》,会有什么发现?
    FPGA 20个例程篇:14.千兆网口实现ICMP、UDP通信协议(下)
    Sentinel 滑动窗口实现原理(源码分析)
    Android获取时间的方式-SystemClock
    【深度学习实验】前馈神经网络(三):自定义两层前馈神经网络(激活函数logistic、线性层算子Linear)
  • 原文地址:https://blog.csdn.net/feiying0canglang/article/details/127113231