文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  內部鎖定方法

10.11.1 內部鎖定方法

本節討論內部鎖定;也就是說,MySQL 伺服器本身執行的鎖定,以管理多個工作階段對資料表內容的爭用。此類型的鎖定是內部的,因為它完全由伺服器執行,且不涉及其他程式。如需其他程式對 MySQL 檔案執行的鎖定,請參閱第 10.11.5 節,〈外部鎖定〉

資料列層級鎖定

MySQL 對 InnoDB 資料表使用資料列層級鎖定,以支援多個工作階段的同時寫入存取,使其適用於多使用者、高度並行和 OLTP 應用程式。

為了避免在單一 InnoDB 資料表上執行多個並行寫入作業時發生死結,請在交易開始時取得必要的鎖定,針對預期修改的每一組資料列發出 SELECT ... FOR UPDATE 語句,即使資料變更語句稍後才在交易中出現。如果交易修改或鎖定多個資料表,請在每個交易中以相同的順序發出適用的語句。死結會影響效能,而不是表示嚴重的錯誤,因為 InnoDB 預設會自動偵測死結情況,並回滾受影響的其中一個交易。

在高並行系統上,當大量執行緒等待相同鎖定時,死結偵測可能會導致效能下降。有時,當發生死結時,停用死結偵測並依賴 innodb_lock_wait_timeout 設定進行交易回滾可能更有效率。可以使用 innodb_deadlock_detect 組態選項停用死結偵測。

資料列層級鎖定的優點

  • 當不同工作階段存取不同資料列時,鎖定衝突較少。

  • 回滾的變更較少。

  • 可以長時間鎖定單一資料列。

資料表層級鎖定

MySQL 對 MyISAMMEMORYMERGE 資料表使用資料表層級鎖定,一次只允許一個工作階段更新這些資料表。此鎖定層級使這些儲存引擎更適合唯讀、幾乎唯讀或單一使用者應用程式。

這些儲存引擎總是要求在查詢開始時一次取得所有需要的鎖定,並總是按相同順序鎖定資料表,以避免死結。折衷方案是,此策略會降低並行性;其他想要修改資料表的工作階段必須等到目前的資料變更語句完成。

資料表層級鎖定的優點

  • 需要的記憶體相對較少(資料列鎖定需要每個資料列或鎖定資料列群組的記憶體)

  • 當在資料表的大部分上使用時,速度很快,因為只涉及單一鎖定。

  • 如果您經常對大部分資料執行 GROUP BY 作業,或必須經常掃描整個資料表,則速度很快。

MySQL 會依下列方式授與資料表寫入鎖定

  1. 如果資料表上沒有鎖定,則在其上放置寫入鎖定。

  2. 否則,將鎖定要求放入寫入鎖定佇列。

MySQL 會依下列方式授與資料表讀取鎖定

  1. 如果資料表上沒有寫入鎖定,則在其上放置讀取鎖定。

  2. 否則,將鎖定要求放入讀取鎖定佇列。

表格更新的優先級高於表格檢索。因此,當鎖定被釋放時,該鎖定會先提供給寫入鎖定佇列中的請求,然後再提供給讀取鎖定佇列中的請求。這確保了即使表格有大量的 SELECT 活動,表格的更新也不會「餓死」。然而,如果表格有許多更新,SELECT 語句會等到沒有更多更新為止。

有關變更讀取和寫入優先順序的資訊,請參閱第 10.11.2 節「表格鎖定問題」

您可以藉由檢查 Table_locks_immediateTable_locks_waited 狀態變數來分析系統上的表格鎖定爭用,這兩個變數分別表示表格鎖定請求可以立即授權的次數,以及必須等待的次數。

mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name         | Value   |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited    | 15324   |
+-----------------------+---------+

Performance Schema 鎖定表格也提供鎖定資訊。請參閱第 29.12.13 節「Performance Schema 鎖定表格」

MyISAM 儲存引擎支援並行插入,以減少給定表格的讀取器和寫入器之間的爭用:如果 MyISAM 表格的資料檔案中間沒有可用區塊,則行會永遠插入到資料檔案的末尾。在這種情況下,您可以自由混合 MyISAM 表格的並行 INSERTSELECT 語句,而無需鎖定。也就是說,您可以在其他客戶端從 MyISAM 表格讀取資料的同時,將資料列插入其中。MyISAM 表格的中間如果有資料列被刪除或更新,就會產生空洞。如果有空洞,則會停用並行插入,但當所有空洞都填滿新資料時,會自動再次啟用。若要控制此行為,請使用 concurrent_insert 系統變數。請參閱第 10.11.3 節「並行插入」

如果您使用 LOCK TABLES 明確取得表格鎖定,您可以請求 READ LOCAL 鎖定,而不是 READ 鎖定,以在您鎖定表格時允許其他會話執行並行插入。

若要對表格 t1 執行多個 INSERTSELECT 作業,而當並行插入不可行時,您可以將資料列插入臨時表格 temp_t1,並使用臨時表格中的資料列更新真實表格。

mysql> LOCK TABLES t1 WRITE, temp_t1 WRITE;
mysql> INSERT INTO t1 SELECT * FROM temp_t1;
mysql> DELETE FROM temp_t1;
mysql> UNLOCK TABLES;

選擇鎖定的類型

一般來說,在下列情況下,表格鎖定優於資料列層級鎖定:

  • 表格的大部分語句都是讀取。

  • 表格的語句是讀取和寫入的混合,其中寫入是可以使用一個金鑰讀取來提取的單一資料列的更新或刪除。

    UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
    DELETE FROM tbl_name WHERE unique_key_col=key_value;
  • SELECT 與並行 INSERT 語句結合使用,以及極少數的 UPDATEDELETE 語句。

  • 在沒有任何寫入器的情況下,對整個表格執行許多掃描或 GROUP BY 作業。

使用較高層級的鎖定,您可以更輕鬆地透過支援不同類型的鎖定來調整應用程式,因為鎖定額外負荷低於資料列層級鎖定。

資料列層級鎖定以外的選項

  • 版本控制(例如 MySQL 中用於並行插入的版本控制),其中可以同時有一個寫入器和多個讀取器。這表示資料庫或表格根據存取開始的時間支援不同的資料檢視。此類型的其他常見術語為「時間旅行」、「寫入時複製」或「依需求複製」。

  • 在許多情況下,依需求複製優於資料列層級鎖定。然而,在最糟的情況下,它會使用比使用正常鎖定更多的記憶體。

  • 您可以使用應用程式層級的鎖定,而不是使用資料列層級鎖定,例如 MySQL 中 GET_LOCK()RELEASE_LOCK() 所提供的鎖定。這些是諮詢鎖定,因此它們僅適用於彼此合作的應用程式。請參閱第 14.14 節「鎖定函數」