Concurrency

只讀事務異常

  • August 8, 2021

我從這些論文中了解到這種異常情況:https ://www.cs.umb.edu/~poneil/ROAnom.pdf (原文)https://johann.schleier-smith.com/blog/2016/01/ 06/analyzing-a-read-only-transaction-anomaly-under-snapshot-isolation.html(簡短易懂的解釋)

有人可以解釋為什麼這被認為是異常情況嗎?AFAIK,只讀事務應該在執行時看到送出的更改,因此結果是正確的。

為什麼它被認為是異常現象?答案在您的連結中引用(強調添加):

從…開始

$$ BBGMOO95 $$,假設只讀事務總是可串列執行,而無需因為並發更新事務而等待或中止。這似乎是不言而喻的,因為所有讀取都發生在某個瞬間,此時所有已送出的事務都已完成其寫入,並且沒有可見的未送出事務的寫入。

正如您所說,除了那個驚喜之外,快照隔離的行為與預期的一樣。

但這並不奇怪:快照隔離 不是 可序列化的隔離(連結到我的文章,重點關注 SQL Server)。

Postgres 通過其實現Serializable Snapshot Isolation模糊了界限。他們聲稱可序列化,從我對其進行的簡短研究來看,這對我來說似乎是合理的。您問題中的第二個連結聲稱發現錯誤率較低,但這可能是由於重試失敗的事務造成的。

該快照不可通過寫入序列化是眾所周知的,例如:

create table a ( x int );
create table b ( x int );

-- Session 1 (snapshot)
insert into a select count(*) from b

-- Session 2 (snapshot, concurrently)
insert into b select count(*) from a

快照隔離允許兩個查詢都返回零——這在任何串列調度中顯然是不可能的。

是的,這是有爭議的,這是隔離行為的缺陷,還是僅僅是事務編寫方式的錯誤。這是SELECT ... FOR UPDATEor(SQL Server 中的 UPDLOCK)是強制的模式之一。

在 MVRC 中,事務有時必須使用鎖讀取行的“目前”版本,而不是行版本控制提供的“一致”版本。每當事務要增加或減少行上的現有值時,這通常是必需的。

在範例場景中,如果第一個事務 (TXN2) 讀取FOR UPDATE它將阻塞第二個讀取器 (TXN1)FOR UPDATE直到它送出,並且 TXN3 將讀取兩行的 pre-TXN2 版本,避免“異常”。

引用自:https://dba.stackexchange.com/questions/297756