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