快速理解 髒讀、不可重複讀、幻讀(解決方法)

髒讀【讀取數據未提交】

一個事務讀取另外一個事務未提交的更新事務。

事務1 事務2
select age from table1 where id = 1 – 結果是 20
update table1 set age = 30 where id = 1 – 這裏沒有提交
select age from table1 where id = 1 – 結果是 30
事務2回滾
備註 正常事務1 的結果應該是20

這裏的事務1就讀取了一條髒數據。 – 髒讀

不可重複讀【前後多次讀取,數據內容不一致】

在一個事務範圍內, 同樣的兩次查詢得到不同的結果。這裏是由於系統中其他的事務提交引起的。

事務1 事務2
select age from table1 where id = 1 – 結果是 20
update table1 set age = 30 where id = 1 – 這裏提交了
select age from table1 where id = 1 – 結果是 30
備註 按照正確邏輯,事務A前後兩次讀取到的數據應該一致

幻讀【前後多次讀取,數據總量不一致】

幻讀是不可重複讀的一種特殊情況, 在同一個事務範圍內, 查詢兩次結果得到條數不一樣。

事務1 事務2
select count(*) from table1 結果是 20
insert into table1 value(9,…) – 這裏提交了
select count(*) from table1 – 結果是 21
備註 按照正確邏輯,事務A前後兩次讀取到的數據總量應該一致

數據庫事務隔離級別

在這裏插入圖片描述

未提交讀

一個事務可以讀取另外一個事務未提交的事務。
1.事務在讀數據時候沒有加鎖。
2.在修改數據的時候只是對事務增加行級共享鎖。產生現象:

事務1在讀取的時候, 事務2也可以進行讀取以及修改。(事務在讀取的時候是不加鎖的)
事務2在這條記錄進行修改時候, 事務1可以進行讀取。(因爲事務在修改的時候只是加了共享鎖),
所以,這樣就會產生髒讀。

當隔離級別設置爲Read uncommitted 時,就可能出現髒讀,如何避免髒讀,請看下一個隔離級別。

讀已提交 Read Committed

讀已提交是PostgreSQL裏的缺省隔離級別。
當一個事務運行在這個隔離級別時, SELECT查詢(沒有FOR UPDATE/SHARE子句)只能看到其它事務已提交的數據。
實際上,SELECT 查詢看到一個在查詢開始運行的瞬間該數據庫的一個快照。 不過,SELECT看得見其自身所在事務中之前的更新的執行結果,即使它們尚未提交。
請注意, 在同一個事務裏兩個相鄰的SELECT命令可能看到不同的快照,因爲其它事務會坑你在兩個SELECT執行期間提交。
不會出現可髒讀,但是不可重複讀

可重複讀 Repeatable Read

即使數據被其他事物修改, 當前事務也不會讀取到新的數據
重複讀事務中的查詢看到的是事務開始時的快照, 而不是該事務內部當前查詢開始時的快照,這樣, 同一個事務內部後面的SELECT命令總是看到同樣的數據,
也就是說,它們看不到 它們自身事務開始之後提交的其他事務所做出的改變。
不會出現可髒讀, 可重複讀, 可以幻讀

可串行化 Serializable

可串行化級別提供最嚴格的事務隔離。這個級別爲所有已提交事務模擬串行的事務執行, 就好像事務將被一個接着一個那樣串行(而不是並行)的執行。
不過,正如可重複讀隔離級別一樣, 使用這個級別的應用必須準備在串行化失敗的時候重新啓動事務。
事實上,該隔離級別和可重複讀希望的完全一樣, 它只是監視這些條件,以所有事務的可能的序列不一致的(一次一個)的方式執行並行的可串行化事務執行的行爲。
這種監測不引入任何阻止可重複讀出現的行爲,但有一些開銷的監測,檢測條件這可能會導致串行化異常 將觸發串行化失敗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章