• 如何减少和处理死锁


    文档版本:8.0
    来源:How to Minimize and Handle Deadlocks
    上一篇:快照读与加锁读

    本篇介绍如何减少死锁的发生,以及出现死锁时如何处理。
    死锁指不同的事务因彼此持有对方等待的锁而不能继续执行的情形。因双方都在等待资源释放,任意一方都不会释放已有的锁。

    正文

    死锁是事务形数据库中的经典问题,但只要死锁的发生不会频繁到完全不能执行某个事务,那么就不算危险。通常,当事务因死锁而回滚时,你需要让你的应用随时做好重新发送事务的准备。

    InnoDB引擎默认使用行锁。即使在事务中插入或删除单行数据,也能触发死锁。因为这些操作并不是真正的“原子的”,在插入或删除时它们会给行的索引值(可能有多个)上锁。

    在前面的 InnoDB中的锁 中解释过:在默认级别REPEATABLE READ下,InnoDB在搜索和扫描索引时使用邻键锁,用于避免幻行。此时InnoDB会无视Where条件的过滤,给每个扫描到的索引值及其间隙上锁。此策略适用于加锁读、INSERT、DELETE,但有一个特殊场景只会上记录锁不会上间隙锁:WHERE条件中涵盖了唯一索引。

    通过以下技巧,你可以处理好死锁,并减少其发生的概率:

    • 随时使用SHOW ENGINE INNODB STATUS找出最近发生死锁的原因,以便调整应用规避死锁。

    • 如果频繁的死锁警告惹人注目,开启innodb_print_all_deadlocks选项以收集额外的调试信息。在MySQL的错误日志中会记录每次死锁的信息,而不仅仅记录最后一次。完成调试后关闭这个选项。

    • 随时准备好重启因死锁而失败的事务。死锁并不危险,重试就好了。

    • 保持事务的短小精悍,以降低冲突的可能性。

    • 做出一系列关联变更后立即提交事务,以降低冲突的可能性。特别是不要让有关联的MySQL会话长时间挂起未提交的事务。

    • 如果使用加锁读(SELECT ... FOR UPDATESELECT ... FOR SHARE),尝试使用更低的隔离级别,如READ COMMITTED

    • 在同一事务内修改多张表,或一张表内的不同行时,每次以相同的顺序执行操作。以便让事务形成清晰的锁操作队列而规避死锁。例如,将数据库操作编排为应用内的函数,或调用SQL序列(即MySQL函数或存储过程),避免将类似的INSERT,UPDATE和DELETE操作分散在代码各处。

    • 精心设计表索引。让查询扫描更少的行数,也就意味着更少的锁。使用EXPLAIN SELECT查看MySQL认为查询最适合使用的索引。

    • 减少锁操作。如果能容忍查询返回老快照中的数据,就不要加FOR UPDATEFOR SHARE子句。READ COMMITTED级别适合这种场景,因为每次快照读都会读取自己的最新快照。

    • 如果这些都不起作用的话,使用表锁来序列化你的事务。要在InnoDB表中正确使用`LOCK TABLES`,需要先执行`SET autocommit = 0` (不要执行`START TRANSACTION`),紧接着执行`LOCK TABLES`,在显式提交事务之前不要调用`UNLOCK TABLES`。举个例子,当你需要写入表t1,读取表t2,你可以这么写:
      SET autocommit=0;
      LOCK TABLES t1 WRITE, t2 READ, ...;
      ... 在表t1和t2上操作 ...
      COMMIT;
      UNLOCK TABLES;
      

      表级锁防止表中的并发更改,通过牺牲响应度避免了死锁。

    • 另一种序列化事务的方式是创建辅助的“信号量”表,其中只包含一行数据。让每个事务在访问其它表之前先更新这一行。这样,所有事务将按串行方式执行。注意InnoDB的即时死锁检测算法同样适用于这种场景,因为此处序列化锁是一个行级锁。而对于MySQL的表级锁,必须使用超时方式来解决死锁。
  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    107. Binary Tree Level Order Traversal II
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    104. Maximum Depth of Binary Tree
    103. Binary Tree Zigzag Level Order Traversal
    102. Binary Tree Level Order Traversal
    系统和进程相关信息
    文件I/0缓冲
    系统编程概念(文件系统mount等函数的使用)
  • 原文地址:https://www.cnblogs.com/notayeser/p/14139526.html
Copyright © 2020-2023  润新知