本頁說明如何在可重複讀取隔離中使用 FOR UPDATE
子句。
可重複讀取和可序列化隔離的 FOR UPDATE
子句鎖定機制不同。與可序列化隔離不同,FOR UPDATE
子句不會在可重複讀取隔離中取得鎖定。如要進一步瞭解 FOR UPDATE
中的鎖定,請參閱在可序列化隔離中,使用 SELECT FOR UPDATE。
如要瞭解如何使用 FOR UPDATE
子句,請參閱 GoogleSQL 和 PostgreSQL
FOR UPDATE
參考指南。
為什麼要使用 FOR UPDATE
子句
當交易以可重複讀取隔離層級執行時,SELECT
陳述式查詢的資料一律會以交易的已建立快照時間戳記傳回。如果交易隨後根據查詢的資料進行更新,而並行交易也更新了查詢的資料,就可能發生正確性問題。詳情請參閱「讀寫衝突和正確性」。
如要確保 SELECT
陳述式查詢的資料在交易提交時仍有效,可以使用 FOR UPDATE
子句搭配可重複讀取隔離層級。使用 FOR UPDATE
可確保交易正確性,即使在讀取和修改資料之間,資料可能已由其他交易修改,也不會受到讀取/寫入衝突影響。
查詢語法
本節提供使用 FOR UPDATE
子句時的查詢語法指南。
最常見的用法是在頂層 SELECT
陳述式中。例如:
SELECT SingerId, SingerInfo
FROM Singers WHERE SingerID = 5
FOR UPDATE;
FOR UPDATE
子句可確保交易提交時,SELECT
陳述式和 SingerID = 5
查詢的資料仍有效,避免並行交易更新查詢資料時可能發生的正確性問題。
用於 WITH 陳述式
在 WITH
陳述式的外部層級查詢中指定 FOR UPDATE
時,FOR UPDATE
子句不會驗證 WITH
陳述式中掃描的範圍。
在下列查詢中,由於 FOR UPDATE
未傳播至一般資料表運算式 (CTE) 查詢,因此系統不會驗證任何掃描範圍。
WITH s AS (SELECT SingerId, SingerInfo FROM Singers WHERE SingerID > 5)
SELECT * FROM s
FOR UPDATE;
如果在 CTE 查詢中指定 FOR UPDATE
子句,系統會驗證 CTE 查詢的掃描範圍。
在下列範例中,系統會驗證 SingerId > 5
所在資料列的 SingerId
和 SingerInfo
儲存格。
WITH s AS
(SELECT SingerId, SingerInfo FROM Singers WHERE SingerId > 5 FOR UPDATE)
SELECT * FROM s;
在子查詢中使用
您可以在具有一或多個子查詢的外層查詢中使用 FOR UPDATE
子句。頂層查詢和子查詢中掃描的範圍會經過驗證,但運算式子查詢除外。
下列查詢會驗證 SingerId > 5.
資料列的 SingerId
和 SingerInfo
儲存格,其中 SingerId > 5.
(SELECT SingerId, SingerInfo FROM Singers WHERE SingerId > 5) AS t
FOR UPDATE;
下列查詢不會驗證 Albums
資料表中的任何儲存格,因為該查詢位於運算式子查詢中。系統會驗證運算式子查詢傳回的資料列,是否包含 SingerId
和 SingerInfo
儲存格。
SELECT SingerId, SingerInfo
FROM Singers
WHERE SingerId = (SELECT SingerId FROM Albums WHERE MarketingBudget > 100000)
FOR UPDATE;
用於查詢檢視區塊
您可以使用 FOR UPDATE
子句查詢檢視區塊,如下列範例所示:
CREATE VIEW SingerBio AS SELECT SingerId, FullName, SingerInfo FROM Singers;
SELECT * FROM SingerBio WHERE SingerId = 5 FOR UPDATE;
定義檢視區塊時,無法使用 FOR UPDATE
子句。
不支援的用途
不支援下列 FOR UPDATE
用途:
- 做為在 Spanner 外部執行程式碼的互斥機制: 請勿在 Spanner 中使用鎖定功能,確保對 Spanner 外部資源的專屬存取權。舉例來說,如果交易遭到重試 (無論是應用程式程式碼明確重試,還是用戶端程式碼隱含重試,例如 Spanner JDBC 驅動程式),Spanner 可能會中止交易,且系統只保證在已提交的嘗試期間持有鎖定。
- 搭配
LOCK_SCANNED_RANGES
提示使用: 您無法在同一個查詢中同時使用FOR UPDATE
子句和LOCK_SCANNED_RANGES
提示,否則 Spanner 會傳回錯誤。詳情請參閱「與LOCK_SCANNED_RANGES
提示的比較」。 - 在全文搜尋查詢中:使用全文搜尋索引的查詢無法使用
FOR UPDATE
子句。 - 在唯讀交易中:
FOR UPDATE
子句僅在讀寫交易中執行的查詢中有效。 - 在 DDL 陳述式中:您無法在 DDL 陳述式中的查詢使用
FOR UPDATE
子句,這些查詢會儲存起來供日後執行。舉例來說,定義檢視區塊時,無法使用FOR UPDATE
子句。
後續步驟
- 瞭解如何在 GoogleSQL 和 PostgreSQL 中使用
FOR UPDATE
子句。 - 瞭解如何在可序列化隔離中,使用 SELECT FOR UPDATE。
- 瞭解
LOCK_SCANNED_RANGES
提示。 - 瞭解 Spanner 中的鎖定。