您好,登錄后才能下訂單哦!
這篇文章給大家介紹MySQL事務(wù)隔離級別有哪些,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
說說事務(wù)的隔離級別吧?
老實說,事務(wù)隔離級別這個問題,無論是校招還是社招,面試官都愛問!然而目前網(wǎng)上很多文章,說句實在話啊,我看了后我都懷疑作者弄懂沒!因為他們對可重復(fù)讀(Repeatable Read)和串行化(serializable)的解析實在是看的我一頭霧水!
再加上很多書都說可重復(fù)讀解決了幻讀問題,比如《mysql技術(shù)內(nèi)幕--innodb存儲引擎》等,不一一列舉了,因此網(wǎng)上關(guān)于事務(wù)隔離級別的文章大多是有問題的,所以再開一文說明!
本文所講大部分內(nèi)容,皆有官網(wǎng)作為佐證,因此對本文內(nèi)容你可以看完后,你完全可以當(dāng)概念記在腦海里,除非官網(wǎng)的開發(fā)手冊是錯的,否則應(yīng)當(dāng)無誤!
另外,本文會重點說一下
可重復(fù)讀(Repeatable Read)是否真的解決幻讀的問題!
開始我先提一下,根據(jù)事務(wù)的隔離級別不同,會有三種情況發(fā)生。即臟讀、不可重復(fù)讀、幻讀。這里我先不提這三種情況的定義,后面在講隔離級別的時候會補上。
這里,大家記住一點,根據(jù)臟讀、不可重復(fù)讀、幻讀定義來看(自己總結(jié),官網(wǎng)沒有),有如下包含關(guān)系:
那么,這張圖怎么理解呢?
即,如果發(fā)生了臟讀,那么不可重復(fù)讀和幻讀是一定發(fā)生的。因為拿臟讀的現(xiàn)象,用不可重復(fù)讀,幻讀的定義也能解釋的通。但是反過來,拿不可重復(fù)讀的現(xiàn)象,用臟讀的定義就不一定解釋的通了!
假設(shè)有表tx_tb如下,pId為主鍵
即READ_UNCOMMITTED,其實這個從隔離名字就可以看出來,一個事務(wù)可以讀到另一個事務(wù)未提交的數(shù)據(jù)!為了便于說明,我簡單的畫圖說明!
如圖所示,一個事務(wù)檢索的數(shù)據(jù)被另一個未提交的事務(wù)給修改了。
官網(wǎng)對臟讀定義的地址為https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_dirty_read
其內(nèi)容為
dirty read
An operation that retrieves unreliable data, data that was updated by another transaction but not yet committed.
翻譯過來就是
檢索操作出來的數(shù)據(jù)是不可靠的,是可以被另一個未提交的事務(wù)修改的!
你會發(fā)現(xiàn),我們的演示結(jié)果和官網(wǎng)對臟讀的定義一致。根據(jù)我們最開始的推理,如果存在臟讀,那么不可重復(fù)讀和幻讀一定是存在的。
即READ_COMMITTED,這個也能看的出來,一個事務(wù)能讀到另一個事務(wù)已提交的數(shù)據(jù)!為了便于說明,我簡單的畫圖說明!
如圖所示,一個事務(wù)檢索的數(shù)據(jù)只能被另一個已提交的事務(wù)修改。
官網(wǎng)對不可重復(fù)讀定義的地址為
https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_non_repeatable_read
其內(nèi)容為
non-repeatable read
The situation when a query retrieves data, and a later query within the same transaction retrieves what should be the same data, but the queries return different results (changed by another transaction committing in the meantime).
翻譯過來就是
一個查詢語句檢索數(shù)據(jù),隨后又有一個查詢語句在同一個事務(wù)中檢索數(shù)據(jù),兩個數(shù)據(jù)應(yīng)該是一樣的,但是實際情況返回了不同的結(jié)果。(同時被另一個正在提交的事務(wù)修改了)!
ps:作者注,這里的不同結(jié)果,指的是在行不變的情況下(專業(yè)點說,主鍵索引沒變),但是主鍵索引指向的磁盤上的數(shù)據(jù)內(nèi)容變了。如果主鍵索引變了,比如新增一條數(shù)據(jù)或者刪除一條數(shù)據(jù),就不是不可重復(fù)讀。
顯然,我們這個現(xiàn)象符合不可重復(fù)讀的定義。下面,大家做一個思考:
這個不可重復(fù)讀的定義,放到臟讀的現(xiàn)象里是不是也可以說的通。顯然臟讀的現(xiàn)象,也就是讀未提交的那個例子,是不是也符合在同一個事務(wù)中返回了不同結(jié)果!
但是反過來就不一定通了,一個事務(wù)A中查詢兩次的結(jié)果在被另一個事務(wù)B改變的情況下,如果事務(wù)B未提交就改變了事務(wù)A的結(jié)果,就屬于臟讀,也屬于不可重復(fù)讀。如果該事務(wù)B提交了才改變事務(wù)A的結(jié)果,就不屬于臟讀,但屬于不可重復(fù)讀。
即REPEATABLE_READ。這里,我改變一下順序,先上幻讀的定義
官網(wǎng)對幻讀定義的地址為
https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_phantom
phantom
A row that appears in the result set of a query, but not in the result set of an earlier query. For example, if a query is run twice within a transaction, and in the meantime, another transaction commits after inserting a new row or updating a row so that it matches the WHERE clause of the query.
翻譯過來就是
在一次查詢的結(jié)果集里出現(xiàn)了某一行數(shù)據(jù),但是該數(shù)據(jù)并未出現(xiàn)在更早的查詢結(jié)果集里。例如,在一次事務(wù)里進行了兩次查詢,同時另一個事務(wù)插入某一行或更新某一行數(shù)據(jù)后(該數(shù)據(jù)符合查詢語句里where后的條件),并提交了!
好了,接下來上圖,大家自己評定該現(xiàn)象是否符合幻讀的定義
顯然,該現(xiàn)象是符合幻讀的定義的。同一事務(wù)的兩次相同查詢出現(xiàn)不同行。下面,大家做一個思考:
這個幻讀的定義,放到上面不可重復(fù)讀的現(xiàn)象里是不是也可以說的通。大家自行思考!
反過來就不一定通了。事務(wù)第二次查詢出了一個數(shù)據(jù),但是該數(shù)據(jù)并未出現(xiàn)在***次查詢的結(jié)果集里。如果該數(shù)據(jù)是修改數(shù)據(jù),那么該現(xiàn)象既屬于不可重復(fù)讀,也屬于幻讀。如果該數(shù)據(jù)是新增或刪除的數(shù)據(jù),那該現(xiàn)象就不屬于不可重復(fù)讀,但屬于幻讀。
接下來說一下,為什么很多文章都產(chǎn)生誤傳,說是可重復(fù)讀可以解決幻讀問題!原因出自官網(wǎng)的一句話
地址:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html#innodb-record-locks
原文內(nèi)容如下
By default, InnoDB operates in REPEATABLE READ transaction isolation level. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rows (see Section 14.7.4, “Phantom Rows”).
按照原本這句話的意思,應(yīng)該是
InnoDB默認(rèn)用了REPEATABLE READ。在這種情況下,使用next-key locks解決幻讀問題!
結(jié)果估計,某個國內(nèi)翻譯人員翻著翻著變成了
InnoDB默認(rèn)用了REPEATABLE READ。在這種情況下,可以解決幻讀問題!
然后大家繼續(xù)你抄我,我抄你,結(jié)果你懂的!
顯然,漏了"使用了next-key locks!"這個條件后,意思完全改變,我們在該隔離級別下執(zhí)行語句
select * from tx_tb where pId >= 1;
是快照讀,是不加任何鎖的,根本不能解決幻讀問題,除非你用
select * from tx_tb where pId >= 1 lock in share mode;
這樣,你就用上了next-key locks,才能解決幻讀問題!
即SERIALIZABLE_READ。在該隔離級別下,所有的select語句后都自動加上lock in share mode。因此,在該隔離級別下,無論你如何進行查詢,都會使用next-key locks。所有的select操作均為當(dāng)前讀!
OK,注意看上表紅色部分!就是因為在該隔離級別下使用了next-key locks,innodb將pId=1這條索引記錄,和(1,++∞)這個間隙鎖住了。其他事務(wù)要在這個間隙上插數(shù)據(jù),就會阻塞,從而防止幻讀發(fā)生!
有的人會說,你這第二次查詢的結(jié)果,也變了啊,明顯和***次查詢結(jié)果不一樣啊?對此,我只能說,請看清楚啊。這是被自己的事務(wù)改的,不是被其他事物修改的。這不算是幻讀,也不是不可重復(fù)讀。
上面羅里吧嗦一大堆,***來一個表格做總結(jié)吧,你面試答這個表就行。上面的一切是為了這張表做準(zhǔn)備!
關(guān)于MySQL事務(wù)隔離級別有哪些就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。