InnoDB
表格使用列級鎖定,因此多個工作階段和應用程式可以同時從同一個表格讀取和寫入,而不會讓彼此等待或產生不一致的結果。對於此儲存引擎,請避免使用 LOCK TABLES
語句,因為它沒有提供任何額外的保護,反而會降低並行性。自動列級鎖定使這些表格適合您最繁忙的資料庫,其中包含最重要的資料,同時也簡化了應用程式邏輯,因為您不需要鎖定和解除鎖定表格。因此,InnoDB
儲存引擎是 MySQL 中的預設引擎。
MySQL 對於除 InnoDB
之外的所有儲存引擎都使用表格鎖定(而不是頁面、列或欄位鎖定)。鎖定操作本身沒有太多負擔。但是,由於一次只能有一個工作階段寫入表格,因此為了使用這些其他儲存引擎獲得最佳效能,請主要將它們用於經常查詢且很少插入或更新的表格。
在選擇是否使用 InnoDB
或其他儲存引擎建立表格時,請記住以下表格鎖定的缺點
表格鎖定使許多工作階段可以同時從表格讀取,但是如果工作階段想要寫入表格,則必須先取得獨佔存取權,這表示它可能必須等待其他工作階段先完成表格的操作。在更新期間,所有想要存取此特定表格的其他工作階段都必須等待直到更新完成。
當工作階段因磁碟已滿而正在等待並且需要釋放可用空間才能繼續時,表格鎖定會造成問題。在這種情況下,所有想要存取問題表格的工作階段也會處於等待狀態,直到有更多磁碟空間可用。
執行時間較長的
SELECT
語句會阻止其他工作階段在這段時間內更新表格,使得其他工作階段顯得緩慢或沒有反應。當工作階段正在等待取得表格的獨佔存取權以進行更新時,其他發出SELECT
語句的工作階段會在它後面排隊,即使對於唯讀工作階段也會降低並行性。
以下項目說明一些避免或減少因表格鎖定引起的爭用的方法
考慮將資料表切換至
InnoDB
儲存引擎,可以在設定時使用CREATE TABLE ... ENGINE=INNODB
,或者對現有的資料表使用ALTER TABLE ... ENGINE=INNODB
。關於此儲存引擎的詳細資訊,請參閱第 17 章,InnoDB 儲存引擎。最佳化
SELECT
語句,使其執行速度更快,從而縮短鎖定資料表的時間。您可能需要建立一些彙總資料表來達成此目的。啟動 mysqld 時使用
--low-priority-updates
選項。對於僅使用資料表層級鎖定的儲存引擎(例如MyISAM
、MEMORY
和MERGE
),這會讓所有更新(修改)資料表的語句的優先權低於SELECT
語句。在這種情況下,先前情境中的第二個SELECT
語句會在UPDATE
語句之前執行,並且不會等待第一個SELECT
語句完成。若要指定在特定連線中發出的所有更新都應以低優先權執行,請將
low_priority_updates
伺服器系統變數設定為 1。若要給特定的
SELECT
語句較高的優先權,請使用HIGH_PRIORITY
屬性。請參閱第 15.2.13 節,「SELECT 語句」。啟動 mysqld 時,將
max_write_lock_count
系統變數設定為較低的值,以強制 MySQL 在發生特定次數的資料表寫入鎖定(例如,用於插入操作)後,暫時提升所有正在等待資料表的SELECT
語句的優先權。這允許在一定數量的寫入鎖定後進行讀取鎖定。如果混合使用
SELECT
和DELETE
語句時遇到問題,則DELETE
的LIMIT
選項可能會有幫助。請參閱第 15.2.2 節,「DELETE 語句」。在
SELECT
語句中使用SQL_BUFFER_RESULT
可以幫助縮短資料表鎖定的持續時間。請參閱第 15.2.13 節,「SELECT 語句」。將資料表內容分割成單獨的資料表可能會有所幫助,這樣可以讓查詢針對一個資料表中的欄位執行,同時將更新限制在不同資料表中的欄位。
您可以變更
mysys/thr_lock.c
中的鎖定程式碼以使用單一佇列。在這種情況下,寫入鎖定和讀取鎖定將具有相同的優先權,這可能對某些應用程式有所幫助。