資料庫的事務對資料并行訪問的時候,有可能會出現一些問題,因此資料庫設定了四個不同的隔離級別來解決問題,
在 MySQL 資料庫的隔離級別可以分為四層,分別是讀未提交、讀提交、可重復讀和串行化,與之對應出現的問題有臟讀、幻讀、不可重復讀,
隔離級別
讀未提交(read uncommited)
一個事務還未提交時,它做的變更就能被其他的事務看到,
讀提交(read commited)
一個事務提交之后,它做的變更才會被其他事務看到
可重復讀(repeatable read)
一個事務執行程序中看到的資料,總是跟這個事務啟動時看到的資料是一致的,在此隔離級別下,未提交的事務對其他事務也是不可見的,
串行化(serializable)
對同一行記錄,“寫” 會加 “寫鎖”,“讀” 會加 “讀鎖”,當出現讀寫鎖沖突的時候,后訪問的事務必須等前一個事務執行完成,才能繼續執行,
此隔離級別保證了資料的正確性,但是頻繁的加鎖會對性能造成嚴重的影響,
不同的事務隔離級別對應的問題
臟讀
在 “讀未提交” 級別下,未提交的變更被其他事務看到了,對其他事務來說,這些未提交的變更就是臟資料,這樣的現象就稱之為“臟讀”,
不可重復讀
在 “讀提交” 級別下,只有事務提交之后,別的事務才能看到事務做的更改,但是當一個事務 A 在執行程序中多次查詢某個值,第一次查詢的時候值為 v1, 然后在事務 B 把值修改了,當事務 A 再次查詢的時候,就會發現這個值不一樣了,明明是同一個事務進行的查詢操作,兩次查詢出來的結果卻不同,這就是“不可重復讀”
幻讀
“幻讀” 與 “不可重復讀” 比較類似,事務 A 查詢某個值,如果不存在,就插入,當事務 A 查詢到不存在之后,事務 B 插入了這個值,事務 A 再去插入的時候就會發現之前查詢不存在的值居然有了,解決幻讀的方法就是設定事務隔離級別為“串行化”,即無論讀寫,都對資料加鎖,
用下面這個程序來展示一下區別
| 事務A | 事務B |
|---|---|
| 啟動事務A, 查詢得到值1 |
啟動事務B |
| 查詢得到值1 | |
| 將1改為2 | |
| 查詢得到值 v1 | |
| 提交事務B | |
| 查詢得到值 v2 | |
| 提交事務 A | |
| 查詢得到值 v3 |
- 若隔離級別是“讀未提交”,則 v1 的值就是2.這時候事務 B 雖然還沒有提交,但是結果已經被 A 看到了,因此, v2、v3 都是 2,
- 若隔離級別是“讀提交”,則 v1 是 1, v2 的值是 2.事務 B 的更新在提交后才能被 A 看到,所以, v3 的值也是 2.
- 若隔離級別是“可重復讀”,則 v1、v2 是 1,v3 是 2,在“可重復讀”級別下需要遵循這個要求:事務在執行期間看到的資料前后必須都是一直的,
- 若隔離級別是“串行化”,則在事務 B 執行“將1改為2”的時候,會被鎖住,知道事務 A 提交之后,事務 B 才可以繼續執行,所以從 A 的角度看,v1、v2的值是 1,v3 的值是 2.
在事務的隔離級別實作上,資料庫里面會創建一個視圖,訪問的時候以視圖的邏輯結果為準,
- 在“可重復讀”隔離級別下,這個視圖是在事務啟動時創建的,整個事務執行期間都使用這個視圖;
- 在“讀提交”級別下,這個視圖是在每個 SQL 陳述句開始執行的時候創建的;
- 如果是“讀未提交”級別,直接回傳記錄上的最新值,沒有視圖概念;而在“串行化”級別下直接用加鎖的方式來避免并行訪問,
公眾號:沒有夢想的阿巧 后臺回復 "群聊",一起學習,一起進步
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/179281.html
標籤:其他
上一篇:如何理解 HTTPS
