簡體   English   中英

Postgres:SELECT FOR UPDATE 在鎖定釋放后看不到新行

[英]Postgres: SELECT FOR UPDATE does not see new rows after lock release

嘗試在我的應用程序中支持 PostgreSQL DB 時,發現了這種奇怪的行為。

准備:

CREATE TABLE test(id INTEGER, flag BOOLEAN);
INSERT INTO test(id, flag) VALUES (1, true);

假設有兩個並發事務( Autocommit=false, READ_COMMITTEDTX1TX2

TX1:

UPDATE test SET flag = FALSE WHERE id = 1;
INSERT INTO test(id, flag) VALUES (2, TRUE);
-- (wait, no COMMIT yet)

TX2:

SELECT id FROM test WHERE flag=true FOR UPDATE;
-- waits for TX1 to release lock

現在,如果我在TX1 中COMMIT ,則 TX2 中的 SELECT 返回空游標。

這對我來說很奇怪,因為 Oracle 和 MariaDB 中的相同實驗導致選擇新創建的行 (id=2)。

我在 PG 文檔中找不到有關此行為的任何信息。 我錯過了什么嗎? 有沒有辦法強制PG服務器在獲取鎖后“刷新”語句可見性?

PS:PostgreSQL 11.1 版

TX2掃描表並嘗試鎖定結果。

掃描從查詢開始就看到了數據庫的快照,因此它看不到在拍攝快照開始的並發修改插入(或以其他方式使其符合條件)的任何行。

這就是為什么您看不到id 2 的行的原因。

對於id 1,這也是正確的,因此掃描會找到該行。 但是查詢必須等到鎖被釋放。 當這最終發生時,它獲取該行的最新提交版本並再次執行檢查,因此該行也被排除在外。

這種“EvalPlanQual”重新檢查(使用 PostgreSQL 術語)僅對掃描期間發現但被鎖定的行執行。 在掃描過程中甚至沒有找到第二行,所以那里沒有發生這樣的處理。

這有點奇怪,承認。 但這不是錯誤,它只是 PostgreSQL 的工作方式。

如果要避免此類異常,請使用REPEATABLE READ隔離級別。 那么在這種情況下你會得到一個序列化錯誤並且可以重試事務,從而避免這樣的不一致。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM