<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>死锁 on Leanku 的博客</title><link>https://www.leanku.com/tags/%E6%AD%BB%E9%94%81/</link><description>Recent content in 死锁 on Leanku 的博客</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 13 Nov 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://www.leanku.com/tags/%E6%AD%BB%E9%94%81/index.xml" rel="self" type="application/rss+xml"/><item><title>MySQL 死锁：产生原因、分析与解决</title><link>https://www.leanku.com/post/database/mysql-deadlock-analysis-and-resolution/</link><pubDate>Mon, 13 Nov 2023 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/database/mysql-deadlock-analysis-and-resolution/</guid><description>&lt;h1 id="mysql-死锁产生原因分析与解决"&gt;MySQL 死锁：产生原因、分析与解决&lt;/h1&gt;&#10;&lt;p&gt;在高并发系统中，数据库死锁是比较常见的问题。&lt;/p&gt;&#10;&lt;p&gt;很多开发者第一次遇到死锁时，会认为：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;数据库是不是出问题了？&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;实际上，死锁本身并不意味着 MySQL 出现了故障。对于 InnoDB 来说，死锁是并发事务之间形成循环等待后，由存储引擎主动检测并处理的一种正常机制。&lt;/p&gt;&#10;&lt;p&gt;真正需要解决的问题不是简单地“关闭死锁”，而是：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么会产生死锁？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;哪些 SQL 导致了循环等待？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么某个事务被回滚？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;如何从根本上减少死锁？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;应用程序收到死锁异常后应该怎么处理？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;理解这些问题，才能正确处理生产环境中的死锁。&lt;/p&gt;&#10;&lt;h2 id="1-什么是死锁"&gt;1. 什么是死锁&lt;/h2&gt;&#10;&lt;p&gt;死锁（Deadlock）是指两个或多个事务互相持有对方需要的锁，同时等待对方释放锁，最终形成循环等待。&lt;/p&gt;&#10;&lt;p&gt;例如有两个账户：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;账户 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;账户 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;事务 A：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;锁住账户 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;等待账户 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;事务 B：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;锁住账户 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;等待账户 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最终形成：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;事务 A → 等待事务 B 持有的锁&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;事务 B → 等待事务 A 持有的锁&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这就是典型的死锁。&lt;/p&gt;&#10;&lt;p&gt;需要注意，&lt;strong&gt;死锁和锁等待不是一回事&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;普通锁等待可能是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;事务 A 持有锁&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;事务 B 等待事务 A&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;只要事务 A 最终提交或回滚，事务 B 就可以继续执行。&lt;/p&gt;</description></item></channel></rss>