文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 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 參考手冊  /  函數與運算子  /  鎖定函數

14.14 鎖定函數

本節描述用於操作使用者層級鎖定的函數。

表 14.19 鎖定函數

名稱 描述
GET_LOCK() 取得具名鎖定
IS_FREE_LOCK() 具名鎖定是否可用
IS_USED_LOCK() 具名鎖定是否正在使用中;如果為真,則傳回連線識別碼
RELEASE_ALL_LOCKS() 釋放所有目前具名鎖定
RELEASE_LOCK() 釋放具名鎖定

  • GET_LOCK(str,timeout)

    嘗試取得名稱為字串 str 的鎖定,使用的逾時時間為 timeout 秒。負數的 timeout 值表示無限逾時。鎖定是獨佔的。當一個工作階段持有鎖定時,其他工作階段無法取得相同名稱的鎖定。

    如果成功取得鎖定,則傳回 1;如果嘗試逾時 (例如,因為另一個用戶端先前已鎖定該名稱),則傳回 0;如果發生錯誤 (例如,記憶體不足或執行緒被 mysqladmin kill 終止),則傳回 NULL

    使用 GET_LOCK() 取得的鎖定,會透過執行 RELEASE_LOCK() 明確釋放,或在您的工作階段終止時 (正常或異常終止) 隱含釋放。使用 GET_LOCK() 取得的鎖定,在交易提交或回滾時不會釋放。

    GET_LOCK() 是使用中繼資料鎖定 (MDL) 子系統實作的。可以同時取得多個鎖定,且 GET_LOCK() 不會釋放任何現有鎖定。例如,假設您執行以下陳述式

    SELECT GET_LOCK('lock1',10);
    SELECT GET_LOCK('lock2',10);
    SELECT RELEASE_LOCK('lock2');
    SELECT RELEASE_LOCK('lock1');

    第二個 GET_LOCK() 會取得第二個鎖定,且兩個 RELEASE_LOCK() 呼叫都會傳回 1 (成功)。

    甚至可以讓給定的工作階段取得同一個名稱的多個鎖定。在取得鎖定的工作階段釋放該名稱的所有鎖定之前,其他工作階段無法取得該名稱的鎖定。

    使用 GET_LOCK() 取得的唯一命名鎖定,會出現在效能結構描述 metadata_locks 表格中。OBJECT_TYPE 欄表示 USER LEVEL LOCK,而 OBJECT_NAME 欄表示鎖定名稱。如果針對相同名稱取得多個鎖定,則只有該名稱的第一個鎖定會在 metadata_locks 表格中註冊一個資料列。後續該名稱的鎖定會增加鎖定中的計數器,但不會取得額外的中繼資料鎖定。當釋放該名稱的最後一個鎖定執行個體時,會刪除該鎖定的 metadata_locks 資料列。

    取得多個鎖定的能力表示用戶端之間可能發生死鎖。當發生這種情況時,伺服器會選擇一個呼叫者,並以 ER_USER_LOCK_DEADLOCK 錯誤終止其鎖定取得要求。此錯誤不會導致交易回滾。

    MySQL 會對鎖定名稱強制執行 64 個字元的最大長度限制。

    GET_LOCK() 可用於實作應用程式鎖定或模擬記錄鎖定。名稱是在伺服器範圍內鎖定的。如果名稱在一個工作階段內被鎖定,則 GET_LOCK() 會封鎖另一個工作階段對相同名稱鎖定的任何要求。這使就給定鎖定名稱達成一致的用戶端能夠使用該名稱執行協作建議鎖定。但請注意,這也使不屬於協作用戶端集合的用戶端能夠無意或故意鎖定名稱,從而阻止任何協作用戶端鎖定該名稱。減少這種情況發生的一種方法是使用特定於資料庫或特定於應用程式的鎖定名稱。例如,使用 db_name.strapp_name.str 格式的鎖定名稱。

    如果有多個用戶端正在等待鎖定,則取得鎖定的順序是不確定的。應用程式不應假設用戶端會以發出鎖定要求的相同順序取得鎖定。

    GET_LOCK() 對於基於陳述式的複寫是不安全的。如果當 binlog_format 設定為 STATEMENT 時使用此函數,則會記錄警告。

    由於 GET_LOCK() 僅在單一 mysqld 上建立鎖定,因此不適合與 NDB Cluster 一起使用,NDB Cluster 沒有跨多個 MySQL 伺服器強制執行 SQL 鎖定的方法。如需詳細資訊,請參閱 第 25.2.7.10 節「與多個 NDB Cluster 節點相關的限制」

    警告

    由於具備取得多個具名鎖定的能力,單一敘述就有可能取得大量的鎖定。例如:

    INSERT INTO ... SELECT GET_LOCK(t1.col_name) FROM t1;

    這些類型的敘述可能會產生某些不利影響。例如,如果敘述執行到一半失敗並回滾,則在失敗點之前取得的鎖定仍然存在。如果目的是讓插入的列和取得的鎖定之間存在對應關係,則這個目的將無法實現。此外,如果鎖定必須按照特定順序授予,請注意,結果集的順序可能會因最佳化工具選擇的執行計畫而異。基於這些原因,最好將應用程式限制為每個敘述只呼叫一次鎖定取得。

    另一種不同的鎖定介面可以作為外掛服務或一組可載入函式使用。與 GET_LOCK() 和相關函式提供的介面不同,此介面提供了鎖定命名空間以及不同的讀取和寫入鎖定。詳細資訊,請參閱第 7.6.9.1 節「鎖定服務」

  • IS_FREE_LOCK(str)

    檢查名為 str 的鎖定是否可供使用(即未鎖定)。如果鎖定可用(沒有人使用該鎖定),則傳回 1;如果鎖定正在使用中,則傳回 0;如果發生錯誤(例如,引數不正確),則傳回 NULL

    這個函式對於基於敘述的複製是不安全的。如果當 binlog_format 設定為 STATEMENT 時使用此函式,則會記錄警告。

  • IS_USED_LOCK(str)

    檢查名為 str 的鎖定是否正在使用中(即已鎖定)。如果是,它會傳回持有該鎖定的用戶端工作階段的連線識別碼。否則,它會傳回 NULL

    這個函式對於基於敘述的複製是不安全的。如果當 binlog_format 設定為 STATEMENT 時使用此函式,則會記錄警告。

  • RELEASE_ALL_LOCKS()

    釋放目前工作階段持有的所有具名鎖定,並傳回釋放的鎖定數(如果沒有鎖定,則傳回 0)。

    這個函式對於基於敘述的複製是不安全的。如果當 binlog_format 設定為 STATEMENT 時使用此函式,則會記錄警告。

  • RELEASE_LOCK(str)

    釋放由字串 str 命名的鎖定,該鎖定是透過 GET_LOCK() 取得的。如果鎖定已釋放,則傳回 1;如果鎖定不是由此執行緒建立的(在這種情況下,不會釋放鎖定),則傳回 0;如果具名鎖定不存在,則傳回 NULL。如果從未透過呼叫 GET_LOCK() 取得鎖定,或鎖定先前已釋放,則該鎖定不存在。

    DO 敘述方便與 RELEASE_LOCK() 一起使用。請參閱 第 15.2.3 節,「DO 敘述」

    這個函式對於基於敘述的複製是不安全的。如果當 binlog_format 設定為 STATEMENT 時使用此函式,則會記錄警告。