數據庫事務的四種隔離級別知識 數據庫事務的四種隔離級別

數據庫事務的四種隔離級別

 

數據庫事務的隔離級別有4種,由低到高分別爲Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事務的併發操作中可能會出現髒讀,不可重複讀,幻讀。下面通過事例一一闡述它們的概念與聯繫。

Read uncommitted

讀未提交,顧名思義,就是一個事務可以讀取另一個未提交事務的數據。

事例:老闆要給程序員發工資,程序員的工資是3.6萬/月。但是發工資時老闆不小心按錯了數字,按成3.9萬/月,該錢已經打到程序員的戶口,但是事務還沒有提交,就在這時,程序員去查看自己這個月的工資,發現比往常多了3千元,以爲漲工資了非常高興。但是老闆及時發現了不對,馬上回滾差點就提交了的事務,將數字改成3.6萬再提交。

分析:實際程序員這個月的工資還是3.6萬,但是程序員看到的是3.9萬。他看到的是老闆還沒提交事務時的數據。這就是髒讀

Read committed

讀提交,顧名思義,就是一個事務要等另一個事務提交後才能讀取數據。

事例:程序員拿着信用卡去享受生活(卡里當然是只有3.6萬),當他買單時(程序員事務開啓),收費系統事先檢測到他的卡里有3.6萬,就在這個時候!!程序員的妻子要把錢全部轉出充當家用,並提交。當收費系統準備扣款時,再檢測卡里的金額,發現已經沒錢了(第二次檢測金額當然要等待妻子轉出金額事務提交完)。程序員就會很鬱悶,明明卡里是有錢的…

分析:這就是讀提交,若有事務對數據進行更新(UPDATE)操作時,讀操作事務要等待這個更新操作事務提交後才能讀取數據,可以解決髒讀問題。但在這個事例中,出現了一個事務範圍內兩個相同的查詢卻返回了不同數據,這就是不可重複讀。

Repeatable read

重複讀就是在開始讀取數據(事務開啓)時,不再允許修改操作

事例:程序員拿着信用卡去享受生活(卡里當然是只有3.6萬),當他埋單時(事務開啓,不允許其他事務的UPDATE修改操作),收費系統事先檢測到他的卡里有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就可以扣款了。

分析:重複讀可以解決不可重複讀問題。寫到這裏,應該明白的一點就是,不可重複讀對應的是修改,即UPDATE操作。但是可能還會有幻讀問題。因爲幻讀問題對應的是插入INSERT操作,而不是UPDATE操作

什麼時候會出現幻讀?

事例:程序員某一天去消費,花了2千元,然後他的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啓),看到確實是花了2千元,就在這個時候,程序員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子打印程序員的消費記錄清單時(妻子事務提交),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀。

那怎麼解決幻讀問題?Serializable

Serializable 序列化

Serializable 是最高的事務隔離級別,在該級別下,事務串行化順序執行,可以避免髒讀、不可重複讀與幻讀。但是這種事務隔離級別效率低下,比較耗數據庫性能,一般不使用。

四種隔離級別可能導致的問題:

1、Serializable (串行化):最嚴格的級別,事務串行執行,資源消耗最大;

2、REPEATABLE READ(重複讀) :保證了一個事務不會修改已經由另一個事務讀取但未提交(回滾)的數據。避免了“髒讀取”和“不可重複讀取”的情況,但不能避免“幻讀”,但是帶來了更多的性能損失。

3、READ COMMITTED (提交讀):大多數主流數據庫的默認事務等級,保證了一個事務不會讀到另一個並行事務已修改但未提交的數據,避免了“髒讀取”,但不能避免“幻讀”和“不可重複讀取”。該級別適用於大多數系統。

4、Read Uncommitted(未提交讀) :事務中的修改,即使沒有提交,其他事務也可以看得到,會導致“髒讀”、“幻讀”和“不可重複讀取”。

通俗解釋:

髒讀:所謂的髒讀,其實就是讀到了別的事務回滾前的髒數據。比如事務B執行過程中修改了數據X,在未提交前,事務A讀取了X,而事務B卻回滾了,這樣事務A就形成了髒讀。

也就是說,當前事務讀到的數據是別的事務想要修改成爲的但是沒有修改成功的數據。

不可重複讀:事務A首先讀取了一條數據,然後執行邏輯的時候,事務B將這條數據改變了,然後事務A再次讀取的時候,發現數據不匹配了,就是所謂的不可重複讀了。

也就是說,當前事務先進行了一次數據讀取,然後再次讀取到的數據是別的事務修改成功的數據,導致兩次讀取到的數據不匹配,也就照應了不可重複讀的語義。

幻讀:事務A首先根據條件索引得到N條數據,然後事務B改變了這N條數據之外的M條或者增添了M條符合事務A搜索條件的數據,導致事務A再次搜索發現有N+M條數據了,就產生了幻讀。

也就是說,當前事務讀第一次取到的數據比後來讀取到數據條目不一致。

 


 mysql默認隔離級別

1.查詢mysql全局事務隔離級別

select @@global.tx_isolation;

2.查詢當前會話事務隔離級別

 select @@tx_isolation;

mysql默認事務隔離級別爲重複讀REPEATABLE-READ 可以避免髒讀,不可重複讀,不可避免幻讀

常看當前數據庫的事務隔離級別: show variables like 'tx_isolation';
設置事務隔離級別:set tx_isolation='REPEATABLE-READ';
Mysql默認的事務隔離級別是可重複讀,用Spring開發程序時,如果不設置隔離級別默認用Mysql設置的隔
離級別,如果Spring設置了就用已經設置的隔離級別

爲什麼MySQL的默認隔離離別是RR?

binlog的格式也有三種:statement,row,mixed。設置爲statement格式,binlog記錄的是SQL的原文。又因爲MySQL在主從複製的過程是通過binlog進行數據同步,如果設置爲讀已提交(RC)隔離級別,當出現事務亂序的時候,就會導致備庫在 SQL 回放之後,結果和主庫內容不一致。

 比如:

複製代碼
CREATE TABLE t (  
     a int(11) DEFAULT NULL,  
     b int(11) DEFAULT NULL,  
     PRIMARY KEY a (a),
     KEY b(b)
   ) ENGINE=InnoDB DEFAULT CHARSET=latin1;  
   insert into t1 values(10,666),(20,233); 
複製代碼

讀已提交(RC)隔離級別下,兩個事務執行完後,數據庫的兩條記錄就變成了(30,666)、(20,666)。這兩個事務執行完後,binlog也就有兩條記錄,因爲事務binlog用的是statement格式,事務2先提交,因此update t set b=666 where b=233優先記錄,而update t set a=30 where b=666記錄在後面。

bin log同步到從庫後,執行update t set b=666 where b=233update t set a=30 where b=666記錄,數據庫的記錄就變成(30,666)、(30,666),這時候主從數據不一致啦。

因此MySQL的默認隔離離別選擇了RR而不是RCRR隔離級別下,更新數據的時候不僅對更新的行加行級鎖,還會加間隙鎖(gap lock)。事務2要執行時,因爲事務1增加了間隙鎖,就會導致事務2執行被卡住,只有等事務1提交或者回滾後才能繼續執行。

並且,MySQL還禁止在使用statement格式的binlog的情況下,使用READ COMMITTED作爲事務隔離級別。

我們的數據庫隔離級別最後選的是讀已提交(RC)。

那爲什麼MySQL官方默認隔離級別是RR,而有些大廠選擇了RC作爲默認的隔離級別呢?

  • 提升併發

RC 在加鎖的過程中,不需要添加Gap Lock和 Next-Key Lock 的,只對要修改的記錄添加行級鎖就行了。因此RC的支持的併發度比RR高得多,

  • 減少死鎖

正是因爲RR隔離級別增加了Gap Lock和 Next-Key Lock 鎖,因此它相對於RC,更容易產生死鎖。

 

 解決幻讀

MVCC加上間隙鎖的方式
(1)在快照讀情況下,mysql通過mvcc來避免幻讀。
(2)在當前讀情況下,mysql通過next-key(next-key鎖是記錄鎖和間隙鎖的組合,它指的是加在某條記錄以及這條記錄前面間隙上的鎖)來避免幻讀。鎖住某個條件下的數據不能更改。

可重複讀隔離級別下MySQL是如何解決幻讀問題的

https://my.oschina.net/u/4129361/blog/3048941

https://blog.csdn.net/aaa821/article/details/81017704

 

參考: https://www.cnblogs.com/ubuntu1/p/8999403.html

           http://blog.itpub.net/26736162/viewspace-2638951/

           https://www.cnblogs.com/imfx/p/11202824.html

           https://mp.weixin.qq.com/s/7-go30yu8k48sY-usu2V4Q

 

 

轉https://www.cnblogs.com/dingpeng9055/p/11190203.html

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