天天看點

mysql隔離級别mysql隔離級别(重要)

mysql隔離級别(重要)

說明:

隔離級别是mysql進行事務送出的時候,對資料的一種表現形式,

事務的基本要素(ACID)(重要)

原子性(Atomicity):事務開始後所有操作,要麼全部做完,要麼全部不做,不可能停滞在中間環節。事務執行過程中出錯,會復原到事務開始前的狀态,所有的操作就像沒有發生一樣。也就是說事務是一個不可分割的整體,就像化學中學過的原子,是物質構成的基本機關。

一緻性(Consistency):事務開始前和結束後,資料庫的完整性限制沒有被破壞 。比如A向B轉賬,不可能A扣了錢,B卻沒收到。

隔離性(Isolation):同一時間,隻允許一個事務請求同一資料,不同的事務之間彼此沒有任何幹擾。比如A正在從一張銀行卡中取錢,在A取錢的過程結束前,B不能向這張卡轉賬。

持久性(Durability):事務完成後,事務對資料庫的所有更新将被儲存到資料庫,不能復原。

事務的操作方式

送出使用commit 復原使用 rollback

begin

.....
commit
           

事務的并發問題

髒讀:事務A讀取了事務B更新的資料,然後B復原操作,那麼A讀取到的資料是髒資料

不可重複讀:事務 A 多次讀取同一資料,事務 B 在事務A多次讀取的過程中,對資料作了更新并送出,導緻事務A多次讀取同一資料時,結果 不一緻。

幻讀:系統管理者A将資料庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理者B就在這個時候插入了一條具體分數的記錄,當系統管理者A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

事務隔離級别 髒讀 不可重複讀 幻讀

讀未送出(read-uncommitted) 是 是 是

不可重複讀(read-committed) 否 是 是

可重複讀(repeatable-read) 否 否 是

串行化(serializable) 否 否 否

具體實踐

說明: 我們使用a,b兩個端 a負責開啟事務,并且修改資料。b負責開啟事務,并且在a執行事務的時候不斷去擷取資料。以此研究資料的影響.a先執行,因為a需要去修改資料,是以a要首先擷取到鎖才行

髒讀

首先在b中去設定隔離級别

a用戶端

start transaction
update `Employee` set Name='test2' where Id=1
           

b用戶端

set session transaction isolation level read uncommitted
start transaction
select * from `Employee`
           

這是時候,可以看到a中修改的資料,b中已經可以檢視到,但是a找那個的資料并沒有commit,b讀取到了a還沒有送出上去的髒資料,稱為髒讀

不可複讀

a用戶端

start transaction
update `Employee` set Name='test2' where Id=1
           

b用戶端

set session transaction isolation level read committed
start transaction
select * from `Employee`
           

這時候再去檢視資料就不會出現髒讀的情況,但是在a送出之後,再使用b去檢視的話就會有一定的問題

a用戶端

commit
           

b用戶端

select * from `Employee`
           

這時候b的中表的資料就變了,雖然沒有髒讀的情況,但是b中的資料兩次不一樣, 是以稱之為不可複讀

幻讀

a用戶端

start transaction
update `Employee` set Name='test2' where Id=1
           

b用戶端

set session transaction isolation level REPEATABLE read
start transaction
select * from `Employee`
           

a用戶端

commit
           

b用戶端

select * from `Employee`
           

這個時候,b中檢視的資料沒有沒有問題,他看到的一直都是老資料。這裡使用了mvvc技術

但是有一個問題,當a表去Insert一條資料資料并且commit了之後,b去select的時候就會看到a表中新加的資料,就像幻讀一樣,多出了一條資料來

a

start transaction
insert into `Employee` (name,id)value('test',10
commit
           

為了避免這個問題,b可以設定

set session transaction isolation level serializable
           

在a操作事務的時候,b操作事務會一直卡住,直到a表操作完成b才能去select操作,這就是串行化

mysql預設的級别是不可複讀

搞懂 不可重複讀和幻讀

幻讀

不可重複讀 和 幻讀, 這兩者确實非常相似。

不可重複讀 主要是說多次讀取一條記錄, 發現該記錄中某些列值被修改過。

幻讀 主要是說多次讀取一個範圍内的記錄(包括直接查詢所有記錄結果或者做聚合統計), 發現結果不一緻(标準檔案一般指記錄增多, 記錄的減少應該也算是幻讀)。

總結 不可複讀是針對同一條資料兩次讀取會有變化 幻讀是說當select到資料id=9的時候,這個時候我們可以去插入id=10的資料,但是其他的事務已經插入了id=10的記錄,這個時候就會報錯。但是從本事務的觀點來看id為10的東西是不存在的。是以就想有幻覺一樣,稱為幻讀。

其實對于 幻讀, MySQL的InnoDB引擎預設的RR級别已經通過MVCC自動幫我們(部分)解決了。因為當其他事務增加一條資料的時候。我們兩次執行查詢語句結果都是一樣的。這是使用了mvcc模式來實作的,在RR模式下面,事務每次讀取的都是一個快照。同一個事務中每次都讀取同一份快照。是以就算資料更新了。讀的也是老資料