文章目錄
-
-
-
- 一 定義
- 二 解釋
-
- Read-Uncommited(讀未送出)
- Read-commited(讀已送出)
- Repeatable-Read(可重複讀)
- Serializable(串行化)
- 三 什麼是不可重複讀,什麼是幻讀
-
- 不可重複讀
- 幻讀
-
-
一 定義
mysql的事務隔離級别一共有四個:
- 讀未送出(Read-Uncommited),
- 讀已送出(Read-Commited),
- 可重複讀(Repeatable-Read) ,
- 串行化(Serializable) 。
其中,MySQL的預設的事務隔離級别為可重複讀(Repeatable-Read)。
二 解釋
簡單的介紹一下四種隔離級别:
Read-Uncommited(讀未送出)
在Read Uncommited級别,事務中的修改,即便沒有送出,對其他事務也都是可見的,事務可以讀取未送出的資料,這也是被叫做髒讀(Dirty Read),這種級别會導緻很多問題,從性能上看,Read Uncommited不會比其他的級别好太多,但缺乏其他事務級别的很多好處,除非真的非常有必要的理由,在實際應用中,一般最好不要使用
Read-commited(讀已送出)
大多數資料庫系統的預設隔離級别都是Read Commited(Oracle,但是Mysql不是),Read Commited滿足事務隔離級别的一般定義,一個事務開始時,隻能看到已經送出的事務所做的修改,換句話說,一個事務從開始到送出之前,所做的任何修改對其他事務都是不可見的,這種級别有時候也叫不可重複讀,因為兩次執行同樣的查詢,可能會得到不一樣的結果。
Repeatable-Read(可重複讀)
Repeatable-Read解決了髒讀的問題,該級别保證了在同一個事務中多次讀取同樣記錄的結果是一緻的,但是理論上,可重複讀隔離級别還是無法解決另一種幻讀(Phantom Read)的問題,所謂幻讀,指的是當某個事務在讀取某個範圍内的記錄時,另外一個事務又在該範圍内插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會出現幻行(Phantom Row),Innodb和XtraDB存儲引擎通過多版本并發控制(MVCC ,multuversion concurrencyControl)解決了幻讀的問題,
該級别是Mysql的預設的事務隔離級别
Serializable(串行化)
Serializable是最高的隔離級别,它通過強制事務串行執行,避免了前面說的幻讀問題,簡單來說,Serializable會在讀取的每一行資料上都加鎖,是以可能導緻大量的逾時和鎖競争的問題,實際應用中也是很少使用到這種隔離級别,隻有在非常需要保證資料的一緻性而且可以接收沒有并發的情況下,才考慮使用該事務的隔離級别。
三 什麼是不可重複讀,什麼是幻讀
在去實際區分這兩個定義之前,我們先去了解一下定義:
- 髒讀(Diry Read)實際上在上面個的定義中,已經說明:事務中的修改,即便沒有送出,對其他事務也都是可見的,事務可以讀取未送出的資料,這也是被叫做髒讀
- 不可重複讀:同一事務的兩次同樣的操作執行,會的到不同的結果
- 幻讀:指的是當某個事務在讀取某個範圍内的記錄時,另外一個事務又在該範圍内插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會出現幻行
不可重複讀
檢視mysql目前預設的事務隔離級别:
# 表示查詢目前會話的事務隔離級别
select @@tx_isolation;
# 表示查詢目前全局範圍内mysql的事務隔離級别
select @@global.tx_isolation;
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90TUNJza650ckNzYqB3MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLygjM1UDNzATMxETMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
1,首先示範,設定目前全局mysql的事務隔離級别為讀已送出(Read-commited)
//設定read uncommitted級别:
set session transaction isolation level read uncommitted;
//設定read committed級别:
set session transaction isolation level read committed;
//設定repeatable read級别:
set session transaction isolation level repeatable read;
//設定serializable級别:
set session transaction isolation level serializable;
2,設定事務手動送出,并且在事務A中第一次查詢user_info表的school字段資料,然後再B事務中修改user_info表中的school字段資料,同時送出事務,這個時候再在A事務中查詢user_info表中的school字段資料,會發現兩次同樣的查詢語句對應的結果不一緻
A事務:
B事務:
幻讀
1,修改mysql的事務隔離級别為可重複讀,同樣執行上面的操作,
A事務:
B事務:
此時我們會發現REPEATABLE-READ事務隔離級别是解決了不可重複讀,即A事務中,同樣的執行語句無論B事務是否對其進行修改并送出事務,A事務中的查詢語句結果都是一緻的。
注:在《高性能Mysql》一書中,關于什麼是幻讀進行了這樣的講解:
所謂幻讀,指的是當某個事務在讀取某個範圍内的記錄時,另外一個事務又在該範圍内插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會産生幻行。InnoDB存儲引擎通過多版本并發控制(MVCC)解決了幻讀的問題。
但是:RR的事務隔離級别并沒有解決另一種通常意義上說的也是幻讀現象,那就是insert的情況
舉例:
對于A事務,我們查詢user_info表中沒有對應的浙江大學的school,對于B事務,我們任然在事務中查詢不到對應的浙江大學的school,這個時候,我們在A事務中首先建立了一個school為浙江大學的一列資料并送出事務,此時B事務中根據REPEATABLE-READ事務隔離級别任然是不會查詢到school為浙江大學的一列資料,這個時候我們再在B事務中插入一個school為浙江大學的一列,因為我們在school字段加了唯一索引,這個時候就會出現B事務插入shcool資料重複的問題:
A事務
B事務: