只讀事務異常
我從這些論文中了解到這種異常情況: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 UPDATE
or(SQL Server 中的 UPDLOCK)是強制的模式之一。在 MVRC 中,事務有時必須使用鎖讀取行的“目前”版本,而不是行版本控制提供的“一致”版本。每當事務要增加或減少行上的現有值時,這通常是必需的。
在範例場景中,如果第一個事務 (TXN2) 讀取
FOR UPDATE
它將阻塞第二個讀取器 (TXN1)FOR UPDATE
直到它送出,並且 TXN3 將讀取兩行的 pre-TXN2 版本,避免“異常”。