死鎖是一種情況,其中多個交易無法繼續進行,因為每個交易都持有另一個交易需要的鎖。因為所有相關交易都在等待相同的資源變得可用,所以它們都不會釋放它持有的鎖。
當交易在多個資料表中鎖定列時(透過 UPDATE
或 SELECT ... FOR UPDATE
等陳述式),但以相反的順序時,可能會發生死鎖。當這些陳述式鎖定索引記錄與間隙的範圍時,也可能發生死鎖,因為每個交易都會因時間問題而取得一些鎖,但不會取得其他鎖。如需死鎖範例,請參閱章節 17.7.5.1,「InnoDB 死鎖範例」。
為了減少死鎖的可能性,請使用交易,而不是 LOCK TABLES
陳述式;保持插入或更新資料的交易足夠小,使它們不會長時間保持開啟狀態;當不同的交易更新多個資料表或大範圍的列時,請在每個交易中使用相同的操作順序(例如 SELECT ... FOR UPDATE
);在 SELECT ... FOR UPDATE
和 UPDATE ... WHERE
陳述式中使用的欄位上建立索引。死鎖的可能性不受隔離層級影響,因為隔離層級會變更讀取操作的行為,而死鎖是因寫入操作而發生。如需更多關於避免與從死鎖情況中復原的資訊,請參閱章節 17.7.5.3,「如何最小化與處理死鎖」。
當啟用死鎖偵測(預設值)且發生死鎖時,InnoDB
會偵測到此情況並回滾其中一個交易(受害者)。如果使用 innodb_deadlock_detect
變數停用死鎖偵測,則在發生死鎖時,InnoDB
會依賴 innodb_lock_wait_timeout
設定來回滾交易。因此,即使您的應用程式邏輯正確,您仍然必須處理交易必須重試的情況。若要檢視 InnoDB
使用者交易中的最後一個死鎖,請使用 SHOW ENGINE INNODB STATUS
。如果頻繁的死鎖突顯出交易結構或應用程式錯誤處理的問題,請啟用 innodb_print_all_deadlocks
,將所有死鎖的資訊列印到 mysqld 錯誤日誌中。有關如何自動偵測和處理死鎖的更多資訊,請參閱 第 17.7.5.2 節,「死鎖偵測」。