詳解MySQL 資料庫隔離級別與MVCC

2022-09-21 23:42:16 字數 2330 閱讀 3192

mysql是我們日常生產與學習中最常接觸到的資料庫之一,今天講一講在mysql(或者說其他類似的資料庫)中存在的隔離級別以及用來提高效率的多版本併發控制(mvcc)。

首先我們需要提到乙個概念:事務。什麼是事務?事務就是完成乙個基礎操作的一系列操作語句的乙個集合。例如我要將200元從賬戶a轉移到賬戶b,那麼我可能會進行一下的操作:

a.驗證賬戶a中的餘額是否大於200元。

b.將賬戶a中的餘額減200元。

c.將賬戶b中的餘額加200元。

我們就將上面的abc三個操作成為乙個事務。

這時,我們會注意到我們所說的乙個事務有可能是由多條語句組合而成的,而事務又存在原子性,即事務的執行過程中是不能被打斷的,這就帶來乙個問題,如果在這三步執行過程中有另外的語句插入進來執行,是否會對結果產生影響,因為此時破壞了事務的原子性。而這種插入的情況在併發的環境下是十分常見的。因此,我們(或者說是資料庫引擎)就需要在乙個事務的執行過程中對它進行「保護」,即保證外界的其他事務的語句不能隨意的插進正在執行的事務語句之中,來保證事務的正常執行。這時候我們很容易的會想到「加鎖」這個方法。這其實是一種很籠統的說法,因為加鎖雖然能夠保證事務的正常執行,但是卻會帶來較大的額外開銷,因此合適的時候選擇合適的加鎖方式對查詢效率的影響就非常大。而「鎖」得嚴不嚴,就區分除了集中不同的隔離級別。

這種隔離界別下,讀取資料的時候不受任何影響。即你甚至可以讀取乙個正在被其他事務修改的資料,想讀就讀,想改就改。這當然開銷很小,但是會帶來許多的問題,比如「髒讀」。即讀取到了正在修改但是卻還沒有提交的資料,這就會造成資料讀取的錯誤。從效能上來說,read uncommited不會比其他級別好太多,但是卻帶來了非常多的麻煩的問題,因此在實際中很少使用這個個立即被。

這個級別在read uncommited的基礎上新增了一些規定,是一些資料庫的預設隔離級別。它與read uncommited的區別在於,它規定讀取的時候讀到的資料只能是提交後的資料。舉個例子,資料a在上一次提交之後的值是1,這時候有乙個執行緒進來對a進行修改,將a修改為2,但是此時並未提交事務(commit),在這種情況下,read uncommited級別下讀取到的a的值就是當前的2,但是read commited級別下讀取到的還是上一次提交之後的值,即a為1,必須到修改執行緒將a的值變為2這個事務提交之後讀取到的a的值才是2。這個級別所帶來的問題就是不可重複讀。即上乙個時間讀取到的a的值是1,但是隨著修改執行緒對事務的提交,a的值變為了2,這時候讀到的值就是2了,即執行兩次相同的讀取操作得到的值卻不一樣。

不可重複讀同髒讀的區別在於,髒讀是乙個事務讀取了另一未完成的事務執行過程中的資料,而不可重複讀是乙個事務執行過程中,另一事務提交並修改了當前事務正在讀取的資料。

repeated read在read commited的基礎上又新增了一些約束性的規則,它也是mysql資料庫的預設隔離級別。簡單來說就是在乙個事務的執行期間禁止其他事務對相應的資料進行修改,這就徹底使得乙個事務的執行過程中所查詢到的資料一定是一致的,即解決了髒讀和不可重複讀的問題,但是卻帶來了新的問題,即「幻讀」。

「幻讀」指的是在乙個事務執行過程中雖然禁止了對相應資料的修改,但是其他的事務依然可以插入資料,這時候第乙個事務就會發現會「莫名其妙」多出來一些資料,像是出現了幻覺似的。幻讀和不可重複讀都是讀取了另一條已經提交的事務(這點同髒讀不同),所不同的是不可重複讀查詢的都是同乙個資料項,而幻讀針對的是一批資料整體(比如資料的個數)。

這是最嚴格的乙個隔離級別。它通過強制事務序列執行,避免了幻讀的問題。但是這種隔離級別的開銷極大,一般也不常使用。

各種隔離級別與可能的問題關係如下:

隔離級別

髒讀不可重複讀

幻讀加鎖

read uncomkmjduemited

yesyes

yesno

read commited

noyes

yesno

repeated read

nono

yesno

serializable

nono

noyes

試想一下,如果每次sql操作為了保證資料的一致性與準確性,都需要加乙個行級鎖的話,非常可靠,但是帶來的kmjdue系統開銷與查詢效率的下降也是非常明顯的,因此mvcc就是為了解決這種矛盾而產生的。

首先mvcc會在表中的每一行記錄後面儲存兩個隱藏的列,乙個儲存行的建立時間,乙個儲存行的過期(刪除)時間。這個時間值並不是真的時間,而是乙個系統版本號。事務開始的時刻的系統版本號作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。

a.行版本號小於等於事務版本號

b.刪除版本號未定義或者大於事務版本號

儲存了這兩個版本號之後絕大多數的操作都可以在不加鎖的情況下進行正確的操作,保證了效能和效率。

值得注意的是mvcc只在read commited和repeatable read兩個隔離級別下工作。

資料庫隔離級別詳解

事務 transaction 是資料庫管理系統的執行單位,可以是乙個資料庫操作 如select操作 或者是一組操作序列。事務acid屬性,即原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durability 原子性 保證事務中的所有操作全部執行或全部...

資料庫隔離級別詳解

引用自 髒讀 事務沒提交,提前讀取 髒讀就是指當乙個事務正在訪問資料,並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外乙個事務也訪問這個資料,然後使用了這個資料。不可重複讀 兩次讀的不一致 是指在乙個事務內,多次讀同一資料。在這個事務還沒有結束時,另外乙個事務也訪問該同一資料。那麼,...

mysql資料庫隔離級別

事務的隔離級別 由高到低 1.序列化 serializable 乙個事務乙個事務的執行 2.可重複讀 repeatable read 可重複讀,無論其他事務是否修改並提交了資料,在這個事務中看到的資料值始終不受其他事務影響 mysql資料庫所預設的級別 3.讀已提交 read committed 讀...