一文了解MySQL性能測試及調優中的死鎖處理方法,你還看不明白?

一文了解MySQL性能測試及調優中的死鎖處理方法,你還看不明白?

以下從死鎖檢測、死鎖避免、死鎖解決3個方面來探討如何對MySQL死鎖問題進行性能調優。

死鎖檢測

通過SQL語句查詢鎖表相關信息:

(1)查詢表打開情況

SHOW OPEN TABLES WHERE IN_USE> 0

(2)查詢鎖情況列表

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS

(3)查詢鎖等待信息,其中blocking_lock_id是當前事務在等待的事務

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS

(4)查詢死鎖日誌

SHOW ENGINE INNODB STATUS

這條語句只能顯示最新的一條死鎖,無法完全捕獲到系統發生的所有死鎖信息。

如果想要記錄所有的死鎖日誌,需要打開innodb_print_all_deadlocks參數,將所有的死鎖日誌記錄到errorlog中。

(5)查詢鎖等待時間

SHOW STATUS LIKE '%lock%'

死鎖避免

當有死鎖發生時,通常是由於項目的程序中出現了冗長的事務,或是由於隔離級別設置的不合適等。

我們需要在事務使用中注意以下幾點:

(1)盡量保持事務的短小精悍,做出一系列關聯的更新操作後立即提交事務,以降低死鎖的可能性。特別是不要讓有關聯的MySQL會話長時間掛起未提交的事務。

(2)建議使用更低的隔離級別,如READ COMMITTED。

(3)在同一事務內修改多張表,或一張表內的不同行時,每次以相同的順序執行操作。以便讓事務形成清晰的鎖操作隊列而規避死鎖。

死鎖解決

MySQL數據庫通過死鎖檢測(innodb_deadlock_detect)和死鎖超時時間(innodb_lock_wait_timeout)這兩個參數來進行死鎖解決。

死鎖檢測(innodb_deadlock_detect):在MySQL 8.0中,增加了一個新的動態變量innodb_deadlock_detect,用來控制InnoDB是否執行死鎖檢測。

該參數的默認值為ON,即打開死鎖檢測。開啟後InnoDB在加鎖的時候會檢測加鎖後是否會造成死鎖,如果會加鎖,就回滾代價最小的那一個事務。

死鎖超時時間(innodb_lock_wait_timeout):這個參數可以用來處理檢測不出來的死鎖,或是避免長時間等待較長的事務的情況。

對於高並發的系統,當大量線程等待同一個鎖時,死鎖檢測可能會導致性能的下降。

此時,如果禁用死鎖檢測,而改為依靠參數innodb_lock_wait_timeout來釋放長時間佔用鎖資源的事務可能會更加高效。

也就是說,在確認死鎖檢測功能影響了系統的性能並且禁用死鎖檢測不會帶來負面影響時,可以嘗試關閉innodb_deadlock_detect選項。

另外,如果禁用了InnoDB死鎖檢測,需要及時調整參數innodb_lock_wait_timeout的值,以滿足實際的需求。