事務到底是隔離的還是不隔離的?

2022-09-05 11:03:11 字數 1372 閱讀 7215

在之前很長一段時間內,對事務的隔離機制都僅僅侷限在「背」這個字上,但是對於底層如何實現解決的可重複讀和幻讀等一系列問題還是雲裡霧裡。這篇文章,主要還是講述的是在不可重複讀隔離級別下,多事務之間實現的一致性讀和當前讀以及多事務版本併發控制的細節原理,以便於加深對mysql隔離機制的理解,當然後面還會引入對mysql鎖、索引機制等等的問題,慢慢來吧!

首先我們先以當前事務隔離級別為可重複讀級別,在這個隔離級別中,每個事務在操作時,好像都和其他事務完全沒有任何干係。。我一開始對這個一致性讀的理解是,既然是隔離那是不是每乙個事務都需要copy乙份當前資料快照來為這個作為隔離基礎,但是想了下,感覺太誇張了,這資料量得多大,因為要copy那麼多份,後來看了一位技術大佬的專欄,才恍然大悟,不禁感嘆道mysql的設計者是如此的聰明「絕頂」!

既然用copy資料的方式太浮誇,那麼是否可以利用一種操作日誌的方式來代表每一次操作時他能夠讀到的資料並且允許讀取的資料,就是說當前這個事務在操作時,其他還未提交的事務所產生的日誌當前事務是無法讀取的,這樣是不是就完成了隔離的操作,這個就是mysql事務隔離技術的巨集觀操作,當然,細節還是比較繁瑣的。。

按照可重複讀的定義,乙個事務啟動的時候,能夠看到所有已經提交的事務,而那些未提交的事務是不應該看見的,而這部分未提交的部分,需要被當前事務用乙個陣列記錄下來。。

可以認為乙個事務會記錄這些東西:已提交事務--》未提交事務--》還未開始的事務,當前事務所要讀取的某一行資料如果它的事務id在中間(未提交事務),那麼代表當前這個資料是應該被隔離的,也就是當前事務不應該看見的,而在左邊(已提交事務),是屬於可見範圍內的,如果說當前事務讀取到乙個資料行trx_id,該id屬於中間的,那麼就繼續往前查詢,知道找到第乙個屬於左邊範圍的資料行,以該資料行作為當前事務所能看到的,這個也就是所謂的「一致性讀」,除開一致性讀之外,還有乙個是當前讀,就是必須讀取到最新的資料,這個一般是發生在更新語句和加鎖讀語句時,當前需要讀取或者更改的資料行必須要最新值!

這裡要說明的一點是,所有的事務都是在執行第乙個語句時才啟動,start transaction with consistent snapshot命令做的事就是在可重複讀級別下,做到事務一開啟就立馬建立乙個全事務內共享的檢視,但是在rc級別下就不行了,因為rc級別只能是在每一次sql執行開始時建檢視...其實想想,這也是為什麼rc級別下,只能解決髒讀而不能解決不可重複讀的問題所在:

例如有倆事務a、b,a開始執行事務未提交,此時b開啟事務,ok,b讀到第一條sql,開啟乙個檢視,這個檢視裡a的資料還屬於已提交事務--》未提交事務--》還未開始的事務中的未提交事務,因此只要a一直不提交,b就一直讀不到a的資料,因此髒讀解決,但是問題來了,只要a提交了事務,那麼此時b的一條sql在建立檢視時,a的資料處於已提交事務--》未提交事務--》還未開始的事務中的已提交事務,因此不可重複讀問題產生!!而rr級別因為一旦檢視產生就全事務內不變,因此不可重複讀就避免了!!

08 事務到底是隔離的還是不隔離的?

在第 3 篇文章講事務隔離級別的時候提到過,如果是可重複讀隔離級別,事務 t 啟動的時候會建立乙個檢視 read view,之後事務 t 執行期間,即使有其他事務修改了資料,事務 t 看到的仍然跟在啟動時看到的一樣。也就是說,乙個在可重複讀隔離級別下執行的事務,好像與世無爭,不受外界影響。我給你舉乙...

8 MySQL 事務到底是隔離還是不隔離呢

begin start transaction 命令並不是乙個事務的起點,在執行到它們之後的第乙個操作 innodb 表的語句,事務才真正啟動。馬上啟動乙個事務,可以使用 start transaction with consistent snapshot 這個命令 view,使用查詢語句定義的虛擬...

事務的隔離級別舉例 事務的隔離級別

乙個事務是乙個完整的業務邏輯單元,不能再分,要麼全部執行成功,要麼全部失敗。比如 a給b轉賬100元,a的銀行卡就會少100元,b的銀行卡就會多100元,整個過程要麼全部執行成功,要麼全部失敗。a 原子性。事務是最小的業務邏輯單元。b 一致性。乙個事務必須保證多條dml語句同時成功或失敗。c 隔離性...