本節描述用於操作使用者層級鎖定的函數。
表 14.19 鎖定函數
名稱 | 描述 |
---|---|
GET_LOCK() |
取得具名鎖定 |
IS_FREE_LOCK() |
具名鎖定是否可用 |
IS_USED_LOCK() |
具名鎖定是否正在使用中;如果為真,則傳回連線識別碼 |
RELEASE_ALL_LOCKS() |
釋放所有目前具名鎖定 |
RELEASE_LOCK() |
釋放具名鎖定 |
嘗試取得名稱為字串
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.str
或app_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 節「鎖定服務」。檢查名為
str
的鎖定是否可供使用(即未鎖定)。如果鎖定可用(沒有人使用該鎖定),則傳回1
;如果鎖定正在使用中,則傳回0
;如果發生錯誤(例如,引數不正確),則傳回NULL
。這個函式對於基於敘述的複製是不安全的。如果當
binlog_format
設定為STATEMENT
時使用此函式,則會記錄警告。檢查名為
str
的鎖定是否正在使用中(即已鎖定)。如果是,它會傳回持有該鎖定的用戶端工作階段的連線識別碼。否則,它會傳回NULL
。這個函式對於基於敘述的複製是不安全的。如果當
binlog_format
設定為STATEMENT
時使用此函式,則會記錄警告。釋放目前工作階段持有的所有具名鎖定,並傳回釋放的鎖定數(如果沒有鎖定,則傳回 0)。
這個函式對於基於敘述的複製是不安全的。如果當
binlog_format
設定為STATEMENT
時使用此函式,則會記錄警告。釋放由字串
str
命名的鎖定,該鎖定是透過GET_LOCK()
取得的。如果鎖定已釋放,則傳回1
;如果鎖定不是由此執行緒建立的(在這種情況下,不會釋放鎖定),則傳回0
;如果具名鎖定不存在,則傳回NULL
。如果從未透過呼叫GET_LOCK()
取得鎖定,或鎖定先前已釋放,則該鎖定不存在。DO
敘述方便與RELEASE_LOCK()
一起使用。請參閱 第 15.2.3 節,「DO 敘述」。這個函式對於基於敘述的複製是不安全的。如果當
binlog_format
設定為STATEMENT
時使用此函式,則會記錄警告。