設定事務隔離級別的方式有很多種,上篇文章中只簡單提到了理論知識,這裡資料庫以mysql為例,來動手設定一下事務的隔離級別並觀察一下事務的隔離級別到底起到什麼作用。
我們都知道,每啟動一下mysql,就會獲得乙個資料庫連線,每個資料庫連線有乙個全域性變數@@tx_isolation,表示當前連線中事務的隔離級別。
檢視事務隔離級別
命令列登入mysql,檢視當前事務隔離級別:
select @@tx_isolation;
或者
可以看到mysql預設的事務隔離級別為repeatable-read
檢視系統全域性事務離級別可以用:
select @@global.tx_isolation;
設定事務隔離級別設定當前事務隔離級別
set
session
transaction
isolation
level repeatable read;
設定系統全域性(預設)事務隔離級別
set
global
transaction
isolation
level repeatable read;
read uncommitted測試開啟乙個客戶端a,並設定當前事務模式為read uncommitted(未提交讀),查詢表account的初始值:
在客戶端a的事務提交之前,開啟另乙個客戶端b,更新表account:
這時,雖然客戶端b的事務還沒提交,但是客戶端a就可以查詢到b已經更新的資料:
一旦客戶端b的事務因為某種原因回滾,所有的操作都將會被撤銷,那客戶端a查詢到的資料其實就是髒資料:
read committed測試
針對上面的問題,把客戶端a的事務隔離級別設定為read committed,再重複上面的步驟,會發現b在事務結束之前,a並不能查詢到b所做的操作。
客戶端a的執行結果
客戶端b的執行結果
但是正如上文所說,這種隔離級別下可能導致前事務中多次讀取特定記錄的結果不相同,比如客戶端a事務隔離級別為read committed,在a的乙個事務中,執行兩次相同的查詢,在這兩次查詢的中間,客戶端b對資料進行更改並提交事務,那麼會導致客戶端a的兩次查詢結果不一致,導致「不可重複讀」的麻煩。
客戶端a的執行結果
客戶端b的執行結果
repeatable read測試
同理,如果設定了repeatable read隔離級別,就可以保證在當前事務中多次執行相同查詢的結果集相同,實現「可重複讀」。
同樣以客戶端a設定事務隔離級別為repeatable read為例,執行結果如下:
客戶端a的執行結果
客戶端b的執行結果
上篇文章說到,這種隔離級別會導致「幻讀」,比如客戶端a中事務操作表中符合條件的若干行,同時客戶端b中事務插入符合a操作條件的資料行,然後再提交。究竟會發生什麼nie~~
客戶端a的執行結果
客戶端b的執行結果
結果卻不像我們**的那樣,為客戶端a中的事務設定隔離級別為repeatable read,但在客戶端b中的事務插入資料後,a並沒有出現「幻讀」的現象。查了資料才知道,原來在mysql中,不會出現幻讀。mysql的實現和標準定義的rr隔離級別有差別。
當然,
上篇文章說到的只是sql規範所規定的標準,不同的資料庫具體的實現可能會有些差異,所以還是以實際為準~~
實踐出真知,所以每接觸到一些理論知識時,最好能夠實踐一把,自己動手去探索,總會帶給你意想不到的收貨哦。
資料庫事務隔離級別
資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...
資料庫事務隔離級別
資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...
資料庫事務隔離級別
資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable 這四個級別可以逐個解決髒讀 不可重複讀 幻讀 這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted re...