【MySQL技術內幕】34-lock與latch
這裡還要區分鎖中容易令人混淆的概念lock與 latch。在資料庫中,lock與 latch都可以被稱為“鎖”。但是兩者有著截然不同的含義,本章主要關注的是lock。
latch一般稱為閂鎖(輕量級的鎖),因為其要求鎖定的時間必須非常短。若持續的時間長,則應用的效能會非常差。在 InnoDB儲存引擎中, latch又可以分為 mutex(互斥量)和 relock(讀寫鎖)。其目的是用來保證併發執行緒操作臨界資源的正確性,並且通常沒有死鎖檢測的機制。 lock的物件是事務,用來鎖定的是資料庫中的物件,如表、頁、行。並且一般lock的物件僅在事務 commit或 rollback後進行釋放(不同事務隔離級別釋放的時間可能不同)。此外,lock,正如在大多數資料庫中一樣,是有死鎖機制的。下表顯示了lock與latch的不同。
lock | latch | |
物件 | 事務 | 執行緒 |
保護 | 資料庫內容 | 記憶體資料結構 |
持續時間 | 整個事務過程 | 臨界資源 |
模式 | 行鎖、表鎖、意向鎖 | 讀寫鎖、互斥量 |
死鎖 | 通過 waits-for graph、 time out等機制進行無死鎖檢測與處理機制。 | 無死鎖檢測與處理機制。僅通過應用程式加鎖的順序( lock leveling)保證無死鎖的情況發生 |
存在於 | Lock Manager的雜湊表中 | 每個資料結構的物件中 |
對於 InnoDB儲存引擎中的 latch,可以通過命令SHOW ENGINE INNODB MUTEX來進行檢視。
mysql> show engine innodb mutex; +--------+-----------------------------+----------+ | Type | Name | Status | +--------+-----------------------------+----------+ | InnoDB | rwlock: dict0dict.cc:2685 | waits=1 | | InnoDB | rwlock: dict0dict.cc:1183 | waits=91 | | InnoDB | rwlock: fil0fil.cc:1381 | waits=1 | | InnoDB | rwlock: log0log.cc:838 | waits=81 | | InnoDB | rwlock: btr0sea.cc:195 | waits=1 | | InnoDB | sum rwlock: buf0buf.cc:1460 | waits=12 | +--------+-----------------------------+----------+ 6 rows in set (0.17 sec)
在 Debug版本下,通過命令SHOW ENGINE INNODB MUTEX可以看到 latch的更多資訊,如圖所示。
通過上述的例子可以看出,列Type顯示的總是 InnoDB,列Name顯示的是 latch的資訊以及所在原始碼的位置(行數)。列 Status比較複雜,在 Debug模式下,除了顯示 os_waits,還會顯示 count、 spin_waits、 spin_rounds、 os_yields、 os_wait_times等資訊。其具體含義見下表。
名稱 | 說明 |
count | mutex被請求的次數 |
spin_waits | spin lock(自旋鎖)的次數,InnoDB儲存引擎latch在不能獲得鎖時首先進行自旋,若自旋後還不能獲得鎖,則進入等待狀態 |
spin_rounds | 自旋內部迴圈的總次數,每次自旋的內部迴圈是一個隨機數。 spin rounds/spain waits表示平均每次自旋所需的內部迴圈次數 |
os_waits | 表示作業系統等待的次數。當 spin lock通過自旋還不能獲得 latch時,則會進入作業系統等待狀態,等待被喚醒 |
os_yields | 進行 os_thread_yield喚醒操作的次數 |
os_wait_times | 作業系統等待的時間,單位是ms |
上述所有的這些資訊都是比較底層的,一般僅供開發人員參考。但是用息還是可以通過這些引數進行調優。 相對於 latch的檢視,lock資訊就顯得直觀多了。使用者可以通過命令 SHOW ENGINE INNODB STATUS及 information schema架構下的表 INNODB_TRX、 INNODB_LOCKS、INNODB_LOCK_WAITS來觀察鎖的資訊。