暂无图片
暂无图片
1
暂无图片
暂无图片
1
暂无图片

[ACDU 翻译] MySQL 15.7.5.3 如何最小化和处理死锁

原创 由迪 2022-03-10
813

本节基于第 15.7.5.2 节“死锁检测”中有关死锁的概念信息。它解释了如何组织数据库操作以最小化死锁和应用程序中所需的后续错误处理。

死锁是事务数据库中的一个经典问题,但它们并不危险,除非它们太频繁以至于您根本无法运行某些事务。通常,您必须编写应用程序,以便它们随时准备好在事务因死锁而回滚时重新发出事务。

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

您可以使用以下技术应对死锁并降低其发生的可能性:

  • 随时发出问题 SHOW ENGINE INNODB STATUS以确定最近死锁的原因。这可以帮助您调整应用程序以避免死锁。

  • innodb_print_all_deadlocks 如果频繁的死锁警告引起关注,请通过启用该变量 来收集更广泛的调试信息 。有关每个死锁的信息,而不仅仅是最新的,都记录在 MySQL 错误日志中。完成调试后禁用此选项。

  • 如果由于死锁而失败,请始终准备好重新发出事务。死锁并不危险。再试一次。

  • 保持交易小且持续时间短,以减少它们发生冲突的可能性。

  • 在进行一组相关更改后立即提交事务,以降低它们发生冲突的可能性。特别是,不要让交互式 mysql会话在未提交事务的情况下长时间打开。

  • 如果您使用锁定读取SELECT ... FOR UPDATESELECT ... FOR SHARE),请尝试使用较低的隔离级别,例如 READ COMMITTED.

  • 当修改一个事务中的多个表,或同一个表中的不同行集时,每次都以一致的顺序执行这些操作。然后事务形成定义明确的队列并且不会死锁。例如,将数据库操作组织成应用程序中的函数,或调用存储的例程,而不是在不同的地方编写多个相似的 INSERTUPDATEDELETE语句序列。

  • 为您的表添加精心挑选的索引,以便您的查询扫描更少的索引记录并设置更少的锁。用于 EXPLAIN SELECT确定 MySQL 服务器认为哪些索引最适合您的查询。

  • 使用较少的锁定。如果您有能力允许 a SELECT从旧快照返回数据,请不要在其中添加FOR UPDATEor FOR SHARE子句。在这里使用 READ COMMITTED隔离级别很好,因为同一事务中的每个一致读取都从其自己的新快照中读取。

  • 如果没有其他帮助,请使用表级锁序列化您的事务。LOCK TABLES使用事务表(例如表)的正确方法是使用 (not ) 后跟InnoDB 开始事务,并且在显式提交事务之前不要调用 。例如,如果您需要写入 table 并从 table 读取 ,您可以这样做: SET autocommit = 0START TRANSACTIONLOCK TABLESUNLOCK TABLESt1``t2

    SET autocommit=0; LOCK TABLES t1 WRITE, t2 READ, ...; ... do something with tables t1 and t2 here ... COMMIT; UNLOCK TABLES;
    复制

    表级锁可防止对表的并发更新,避免死锁,但会降低对繁忙系统的响应速度。

  • 序列化事务的另一种方法是创建一个仅包含一行的辅助“信号量”表。让每个事务在访问其他表之前更新该行。这样,所有交易都以串行方式发生。请注意,InnoDB 即时死锁检测算法也适用于这种情况,因为序列化锁是行级锁。使用 MySQL 表级锁,必须使用 timeout 方法来解决死锁。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

墨天轮福利君
暂无图片
3年前
评论
暂无图片 0
您好,您的文章已入选墨力原创作者计划合格奖,10墨值奖励已经到账请查收! ❤️我们还会实时派发您的流量收益。
3年前
暂无图片 点赞
评论