
死鎖Deadlock是多個事務(wù)因循環(huán)等待鎖資源而永久阻塞的現(xiàn)象。它雖然危險但并不可怕MySQL InnoDB 有自動檢測和恢復機制。 死鎖是如何產(chǎn)生的死鎖的產(chǎn)生必須同時滿足四個條件InnoDB 中的死鎖通常源于以下兩種典型場景不同表相反順序事務(wù)A更新表1再更新表2事務(wù)B更新表2再更新表1形成循環(huán)等待。相同表不同范圍事務(wù)A通過范圍條件鎖定一個間隙事務(wù)B鎖定另一個間隙隨后各自嘗試插入對方鎖定的間隙導致死鎖。注意死鎖主要由寫操作UPDATE,DELETE,INSERT,SELECT ... FOR UPDATE引起其發(fā)生概率不受隔離級別直接影響。 MySQL InnoDB 如何處理死鎖MySQL InnoDB 提供了自動處理機制但在極端高并發(fā)下也可能需要人工干預。自動檢測與回滾默認開啟。InnoDB 會構(gòu)建等待圖Wait-for Graph檢測到環(huán)路后會回滾一個事務(wù)“受害者”來打破死鎖。通常選擇修改行數(shù)較少的事務(wù)作為回滾對象。兜底超時機制若禁用自動檢測或死鎖涉及外部鎖則依賴innodb_lock_wait_timeout默認50秒。事務(wù)等待超時后會自動回滾。深度檢測限制當鎖等待關(guān)系過于復雜如超過200個事務(wù)InnoDB 會直接回滾當前事務(wù)避免性能崩潰。? 如何排查死鎖死鎖排查的核心是獲取和分析死鎖日志。獲取死鎖日志查看最近一次死鎖執(zhí)行SHOW ENGINE INNODB STATUS\G在輸出中查找LATEST DETECTED DEADLOCK部分。記錄所有死鎖推薦開啟innodb_print_all_deadlocks ON將所有死鎖記錄到 MySQL 錯誤日志便于長期追蹤。分析死鎖日志日志會清晰展示死鎖的完整鏈條。事務(wù)信息TRANSACTION塊展示了事務(wù)ID和狀態(tài)。持有的鎖HOLDS THE LOCK(S)部分顯示該事務(wù)當前成功獲取的鎖。等待的鎖WAITING FOR THIS LOCK部分顯示該事務(wù)被阻塞的鎖請求?;貪L決策日志末尾會標明哪個事務(wù)被回滾WE ROLL BACK TRANSACTION。定位根因分析日志中的 SQL 語句和鎖資源找出循環(huán)等待的路徑。通常根因是事務(wù)以不一致的順序訪問資源或鎖定的范圍有重疊。? 如何預防死鎖預防優(yōu)于處理以下是最佳實踐強制統(tǒng)一訪問順序所有事務(wù)按相同順序如主鍵升序訪問表和行。保持事務(wù)短小精悍盡快提交減少鎖持有時間。使用合適的索引確保WHERE條件能命中索引避免行鎖升級為表鎖??紤]降低隔離級別若業(yè)務(wù)允許使用READ COMMITTED級別可減少間隙鎖降低死鎖概率。使用INSERT ... ON DUPLICATE KEY UPDATE合并先查后改的邏輯減少鎖請求次數(shù)。 如何從死鎖中恢復死鎖是并發(fā)場景下的常態(tài)需要在應(yīng)用層優(yōu)雅處理。捕獲并重試這是最核心的恢復策略。在代碼中捕獲死鎖異常Deadlock found when trying to get lock; try restarting transaction并進行有限次數(shù)的重試通常1-2次即可成功。 總結(jié)死鎖本質(zhì)多個事務(wù)因循環(huán)等待鎖而無限阻塞。InnoDB策略默認自動檢測并回滾“代價最小”的事務(wù)。核心對策統(tǒng)一資源訪問順序縮短事務(wù)應(yīng)用層重試。不要害怕死鎖是并發(fā)數(shù)據(jù)庫的正?,F(xiàn)象設(shè)計健壯的重試機制是解決問題的關(guān)鍵。