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