2015-05-30 91 views
6

在PostgreSQL中,MVCC concurrency control機制說:查詢獲得的爲什麼MVCC需要鎖定DML語句

MVCC鎖(讀)數據並沒有衝突 鎖獲得的寫入數據,並因此閱讀永遠塊寫 和寫作不會阻塞讀

所以,even for READ_COMMITTED,UPDATE語句將鎖定目前受影響的行所以沒有其它事務可以修改它們,直到當前事務提交或回滾。

如果併發事務對鎖定的行發出UPDATE,則第二個事務將阻塞,直到第一個事務釋放鎖。

  1. 這種行爲trying to prevent the write-write conflicts

  2. 更新丟失仍然可以發生在READ_COMMITTED,作爲第一個事務提交之後,第二個將覆蓋行(即使數據庫已經更新查詢開始和結束的查詢之間變化)。所以如果丟失的更新仍然是可能的,爲什麼第二筆交易還要等待?無法使用行級快照來存儲未提交的事務更改,以避免事務必須等待寫入鎖被釋放?

回答

3

第一個問題的答案是肯定的。沒有DBMS可以支持髒寫入;如果兩個事務T1和T2同時執行,並且T2從T1覆蓋更新,則系統不能處理T1自T2已經發生更新以後發出ROLLBACK的情況。

爲了避免髒寫入,快照隔離的原始定義是「第一個提交者獲勝」 - 即衝突寫入將被允許發生,但只有發出COMMIT的第一個事務才能夠 - 所有其他衝突交易將不得不ROLLBACK。但是這種編程模型有些問題,如果不是浪費的話,因爲一個事務可能會更新數據庫的一個重要部分,但最終只能拒絕提交COMMIT的能力。因此,大多數支持MVCC的DBMS系統使用相當傳統的兩階段鎖定實現「第一次更新」,而不是「第一次提交者獲勝」。

+0

但是由於我們處於READ_COMMITTED狀態,所以不會發生髒讀。我想知道爲什麼不更新獨立的副本,只是在提交時刷新它們。現在,在PostgreSQL中,第二個tx簡單地覆蓋了第一個,但是還有一個阻塞正在進行。爲什麼不使用會話作用域快照,並且在此隔離級別沒有阻塞。 –

+0

我想你的意思是「更新獨立副本」將對應於「第一個提交者獲勝」。系統可以實現這一點 - 但編程模型很奇怪,因爲每個事務都必須準備好處理每個修改「工作」的情況(即它已經完成並且沒有返回錯誤),但事務不能被提交。 –

+0

我想鎖定模型更容易採用,因爲每個數據庫都有一個鎖定層次結構。正如你之前提到的,它不僅僅是行數據,而是所有的索引。 –

相關問題