Sql-Server

尚未讀取的隔離級別和行

  • January 11, 2021

在事務 T1 中的 RR 下,我做了一個

SELECT * FROM mytable WHERE city='London'

在另一個 T2 我做

UPDATE mytable SET price=100 WHERE city='London' and id=5000

T2 是否有可能在 T1 讀取之前讀取、更新和送出有問題的行?

1.如果是這樣,那麼 RR 就不會產生影響,或者在這種情況下,沒有隔離級別會產生影響,因為隔離只涉及它們已經被讀取的行,而不是那些尚未讀取的行。真的嗎?

2.但是SERIALIZIBLE不同嗎?它是否需要鍵範圍鎖,這意味著它會在讀取行之前鎖定它們?在上面的程式碼範例中,SERIALIZIBLE 也是如此

SELECT * FROM mytable WHERE city='London'

採取任何鍵範圍鎖,以防止 T2 進入行並在讀取之前更新?

第一季度

T2 是否有可能在 T1 讀取之前讀取、更新和送出有問題的行?

A1

是的,正如 Paul White 所說:

可重複讀隔離級別保證數據在第一次被讀取後在事務的生命週期內不會改變。

同樣由於鎖升級,查詢可以從行鎖開始,然後升級到全表鎖。如果在獲取行鎖的同時執行更新並且該行尚未被訪問,則不會阻止更新。

第二季度

如果是這樣,那麼 RR 就不會產生影響,或者在這種情況下,沒有隔離級別會產生影響,因為隔離只涉及它們已經被讀取的行,而不是那些尚未讀取的行。真的嗎?

A2

是的,您可以使用帶有TABLOCK提示的全表鎖定來確保整個表都鎖定在 RR 中,但這會降低並發性。

SELECT * FROM dbo.mytable WITH(TABLOCK) WHERE city='London';

當然,如果您無論如何都選擇了大量數據,那麼仍然可能會發生表鎖升級。這通常在 5000 行標記附近,但可以更高/更低。

第三季度

然而 SERIALIZIBLE 有什麼不同嗎?它是否需要鍵範圍鎖,這意味著它會在讀取行之前鎖定它們?那麼上面程式碼範例中的 SERIALIZIBLE 是否會採用任何鍵範圍鎖,以防止 T2 到達該行並在讀取之前進行更新?

A3

是的,它需要範圍鎖,Sunil Agarwal在這裡指出了相等範圍鎖的注意事項:

等式謂詞

  • 如果鍵值存在,則僅當索引不唯一時才進行範圍鎖定。在非唯一索引情況下,

對請求的鍵和下一個鍵進行“範圍”鎖定。如果“next”

鍵不存在,則對“infinity”

值進行範圍鎖定。如果索引是唯一的,那麼鍵上的正常 S 鎖。

  • 如果鍵不存在,則對唯一和非唯一索引的“下一個”鍵進行“範圍”鎖定。如果“next”鍵

不存在,則對“infinity”值進行範圍鎖定。

在您的情況下,鍵存在,並且索引可能不是唯一的,因此您將範圍鎖定到下一個值或無窮大值。

但是我會警惕使用可序列化的隔離級別,它會引入死鎖和其他並發問題。

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