Postgresql
大事務和並發的性能?
如果我有一個數百萬行的表並且我執行一個更新 50k 行的事務,這對性能有什麼影響?
假設它的索引正確,它應該不會花費很長時間,但是鎖定了哪些行以及該表的使用如何受到影響?
- 在事務開始之後和結束之前是否可以讀取事務期間正在更新的行?
- 事務期間未更新的行是否可以在事務開始之後和結束之前讀取?
- 如果另一個事務開始嘗試更改之前未完成的事務正在更改的行,那麼該事務會在開始時失敗還是在嘗試送出之後失敗(假設衝突)?
我的問題是 Postgres 9.3;我假設有變化。
在事務開始之後和結束之前是否可以讀取事務期間正在更新的行?
是的,在 Postgres 中讀取不會阻塞寫入,寫入不會阻塞讀取。Postgres 文件指出:
在內部,通過使用多版本模型(Multiversion Concurrency Control,MVCC)來維護數據一致性。這意味著在查詢數據庫時,每個事務都會看到一段時間前的數據快照(數據庫版本),而不管底層數據的目前狀態如何。
$$ … $$使用 MVCC 並發控制模型而不是鎖定的主要優點是,在 MVCC 中,為查詢(讀取)數據而獲得的鎖與為寫入數據而獲得的鎖不會衝突,因此讀取永遠不會阻塞寫入,寫入永遠不會阻塞讀取。
事務期間未更新的行是否可以在事務開始之後和結束之前讀取?
是的。
如果另一個事務開始嘗試更改之前未完成的事務正在更改的行,那麼該事務會在開始時失敗還是在嘗試送出之後失敗(假設衝突)?
這取決於事務隔離級別以及您是否發出依賴於讀取或盲寫的寫入。使用預設級別Read Committed,第二個事務必須等到第一個事務完成寫入。在更高的事務級別中,其中一個事務可能會因序列化錯誤而中止。
您實際上可以通過執行兩個
psql
會話自己嘗試:第 1 節:
-- first set up a table CREATE TABLE tools (id SERIAL PRIMARY KEY, description STRING); INSERT INTO tools(description) VALUES('scredriver'); INSERT INTO tools(description) VALUES('hammer'); -- now type the following into two psql sessions SESSION 1 | SESSION 2 | BEGIN TRANSACTION; | UPDATE tools | SET description = 'anvil' | WHERE id = 1; | | BEGIN TRANSACTION; |UPDATE tools | SET description = 'wrench' | WHERE id = 1; |-- this transaction is blocked |-- until the other transaction COMMIT TRANSACTION; |-- commits
正如您將看到的,會話 2 將被會話 1 阻止。只有當會話 1 送出時,會話 2 才能繼續。
postgres 文件還包含有關在使用更高事務級別時如何避免阻塞和序列化失敗的性能建議。