MySQL 數(shù)據(jù)庫(kù)隔離級(jí)別 臟讀 VS 不可重讀讀 VS 幻讀 VS 可串行化

所在文集:數(shù)據(jù)庫(kù)


本文的內(nèi)容參考了:

本文會(huì)涉及到數(shù)據(jù)庫(kù)的鎖,請(qǐng)先參見:MySQL InnoDB 鎖 學(xué)習(xí)筆記

數(shù)據(jù)庫(kù)隔離級(jí)別

用于處理 多事務(wù)并發(fā) 的情況。

InnoDB 對(duì)四種類型都支持:

  • READ_UNCOMMITTED:讀取未提交。這是并發(fā)最高,一致性最差的隔離級(jí)別。
  • READ_COMMITTED(RC):讀提交。這是互聯(lián)網(wǎng)最常用的隔離級(jí)別。
  • REPEATABLE_READ(RR):重復(fù)讀。
  • SERIALIZABLE:串行化。這是一致性最好的,但并發(fā)性最差的隔離級(jí)別。

不同事務(wù)的隔離級(jí)別,實(shí)際上是一致性與并發(fā)性的一個(gè)權(quán)衡與折衷。
InnoDB 使用不同的鎖策略來(lái)實(shí)現(xiàn)不同的隔離級(jí)別。

Read UnCommitted 讀取未提交內(nèi)容

InnoDB 實(shí)現(xiàn)方式:select 語(yǔ)句不加鎖。

導(dǎo)致出現(xiàn)臟讀:
A 事務(wù)讀取了 B 事務(wù) 尚未提交 的數(shù)據(jù)并在此基礎(chǔ)上操作,而 B 事務(wù)回滾,則 A 事務(wù)讀到的數(shù)據(jù)為臟數(shù)據(jù)。例如:

A: start transaction
  B: start transaction
  B: update account set balance = 50 where id  = 1
A: select balance from account where id  = 1
  B: rollback
A: update account set balance = 50 + 100 where id  = 1
A: commit
  • B 事務(wù)讀取賬戶余額 100 塊,取錢,將余額修改為 50 塊,但并沒(méi)有提交。
  • A 事務(wù)讀取了 尚未提交 的數(shù)據(jù),認(rèn)為余額是 50 塊。
  • B 事務(wù)回滾。
  • A 事務(wù)存錢 100 塊,將余額計(jì)算為 50 + 100 = 150 塊,此為臟數(shù)據(jù),實(shí)際余額應(yīng)該為 200 塊。

Read Committed(RC)讀取提交內(nèi)容

  • 這是大多數(shù)數(shù)據(jù)庫(kù)系統(tǒng)的默認(rèn)隔離級(jí)別(但不是 MySQL 默認(rèn)的)
  • 它滿足了隔離的簡(jiǎn)單定義:一個(gè)事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變

InnoDB 實(shí)現(xiàn)方式:

  • 普通的 select 使用快照讀(snapshot read),這是一種不加鎖的一致性讀。
  • 加鎖的 selectupdatedelete 等語(yǔ)句,除了在外鍵約束檢查以及重復(fù)鍵檢查時(shí)會(huì)封鎖區(qū)間,其他時(shí)刻都只使用記錄鎖;

導(dǎo)致出現(xiàn)不可重復(fù)讀:
意味著我們?cè)谕粋€(gè)事務(wù)中執(zhí)行完全相同的 select 語(yǔ)句時(shí)可能看到不一樣的結(jié)果。
A 事務(wù)重復(fù)讀取前面讀取過(guò)的數(shù)據(jù),
發(fā)現(xiàn)數(shù)據(jù)變化了
,即被其他事務(wù) B 修改并提交過(guò)了。例如:

A: start transaction
  B: start transaction
A: select balance from account where id  = 1
  B: update account set balance = 50 where id  = 1
  B: commit
A: select balance from account where id  = 1
A: commit
  • A 事務(wù)第一次讀取余額 100 塊。
  • B 事務(wù)讀取賬戶余額 100 塊,取錢,將余額修改為 50 塊,并提交。
  • A 事務(wù)第二次讀取余額,變成了 50 塊。與前一次讀取的結(jié)果不同。

Repeatable Read(RR)可重讀

  • 這是 MySQL InnoDB 的默認(rèn)事務(wù)隔離級(jí)別
  • 它確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù)據(jù)行
  • 此級(jí)別可能出現(xiàn)的問(wèn)題——幻讀(Phantom Read):當(dāng)用戶讀取某一范圍的數(shù)據(jù)行時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)插入了新行,當(dāng)用戶再讀取該范圍的數(shù)據(jù)行時(shí),會(huì)發(fā)現(xiàn)有新的“幻影” 行,例如:
A: start transaction
  B: start transaction
A: select * from account // 只有id = 1
  B: insert into account(id, balance) values(2, 0)
  B: commit
A: select * from account // 發(fā)現(xiàn)有id = 1 和 id = 2
A: commit
  • 很多人容易搞混不可重復(fù)讀和幻讀,確實(shí)這兩者有些相似。但不可重復(fù)讀重點(diǎn)在于 updatedelete,而幻讀的重點(diǎn)在于 insert
  • InnoDB 存儲(chǔ)引擎通過(guò)多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機(jī)制解決了該問(wèn)題

InnoDB 實(shí)現(xiàn)方式:

  • 普通的 select 使用快照讀(snapshot read),這是一種不加鎖的一致性讀。
  • 加鎖的 selectupdatedelete 等語(yǔ)句,它們的鎖,依賴于它們是否在唯一索引上使用了唯一的查詢條件,或者范圍查詢條件:
    • 在唯一索引上使用唯一的查詢條件,會(huì)使用記錄鎖(record lock),而不會(huì)封鎖記錄之間的間隔,即不會(huì)使用間隙鎖(gap lock)與臨鍵鎖(next-key lock)。
    • 范圍查詢條件,會(huì)使用間隙鎖與臨鍵鎖,鎖住索引記錄之間的范圍,避免范圍間插入記錄,以避免產(chǎn)生幻影行記錄,以及避免不可重復(fù)的讀。

Serializable 可串行化

  • 這是最高的隔離級(jí)別
  • 它通過(guò)強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決幻讀問(wèn)題。簡(jiǎn)言之,它是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖。
  • 在這個(gè)級(jí)別,可能導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競(jìng)爭(zhēng)

InnoDB 實(shí)現(xiàn)方式:這種事務(wù)的隔離級(jí)別下,所有 select 語(yǔ)句都會(huì)被隱式的轉(zhuǎn)化為 select ... in share mode.

總結(jié)

InnoDB 實(shí)現(xiàn)了SQL92標(biāo)準(zhǔn)中的四種隔離級(jí)別

  • 讀未提交:select 不加鎖,可能出現(xiàn)讀臟;
  • 讀提交(RC):普通 select 快照讀,帶鎖的 select / update / delete 會(huì)使用記錄鎖,可能出現(xiàn)不可重復(fù)讀;
  • 可重復(fù)讀(RR):普通 select 快照讀,帶鎖的 select / update / delete 根據(jù)查詢條件情況,會(huì)選擇記錄鎖,或者間隙鎖/臨鍵鎖,以防止讀取到幻影記錄;
  • 串行化:select 隱式轉(zhuǎn)化為 select ... in share mode,會(huì)被 updatedelete 互斥;
  • InnoDB默認(rèn)的隔離級(jí)別是RR,用得最多的隔離級(jí)別是RC

InnoDB,快照讀,在RR和RC下有何差異?

參考:InnoDB,快照讀,在RR和RC下有何差異?

MySQL 數(shù)據(jù)庫(kù),InnoDB 存儲(chǔ)引擎,為了提高并發(fā),使用 MVCC 機(jī)制,在并發(fā)事務(wù)時(shí),通過(guò)讀取數(shù)據(jù)行的歷史數(shù)據(jù)版本,不加鎖,來(lái)提高并發(fā)的一種不加鎖一致性讀(Consistent Nonlocking Read)

  • 事務(wù)總能夠讀取到,自己寫入(update / insert / delete)的行記錄
  • 在 Read Committed(RC)下,快照讀總是能讀到最新的行數(shù)據(jù)快照,當(dāng)然,必須是已提交事務(wù)寫入的
  • 在 Repeatable Read(RR)下,假設(shè)某個(gè)事務(wù)首次 read 記錄的時(shí)間為 T,則未來(lái)不會(huì)讀取到 T 時(shí)間之后已提交事務(wù)寫入的記錄,以保證連續(xù)相同的 read 讀到相同的結(jié)果集

例如:數(shù)據(jù)表中的數(shù)據(jù)為 {1, 2, 3},現(xiàn)在兩個(gè)并發(fā)事務(wù) A,B 執(zhí)行的時(shí)間序列如下:

A1: start transaction;
         B1: start transaction;
A2: select * from t;
         B2: insert into t values (4, wangwu);
A3: select * from t;
         B3: commit;
A4: select * from t;

在 Read Committed(RC) 模式下:

  • A2 讀到的結(jié)果集是 {1, 2, 3}
  • A3 讀到的結(jié)果集也是 {1, 2, 3},因?yàn)?B 還沒(méi)有提交;
  • A4 讀到的結(jié)果集還是 {1, 2, 3, 4},因?yàn)槭聞?wù) B 已經(jīng)提交;

在 Repeatable Read(RR) 模式下:

  • A2 讀到的結(jié)果集肯定是 {1, 2, 3},這是事務(wù)A的第一個(gè) read,假設(shè)為時(shí)間T;
  • A3 讀到的結(jié)果集也是 {1, 2, 3},因?yàn)?B 還沒(méi)有提交;
  • A4 讀到的結(jié)果集還是 {1, 2, 3},因?yàn)槭聞?wù) B 是在時(shí)間 T 之后提交的,A4 得讀到和 A2 一樣的記錄;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容

  • 一、數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別 數(shù)據(jù)庫(kù)事務(wù)的隔離級(jí)別有4個(gè),由低到高依次為Read uncommitted 、Read c...
    atok閱讀 1,612評(píng)論 2 10
  • 數(shù)據(jù)庫(kù)中經(jīng)常被問(wèn)到四大特性和隔離級(jí)別,一般都是涉及到概念性問(wèn)題,在此做一些整理總結(jié),方便理解。 1、事務(wù)的隔離級(jí)別...
    Hughman閱讀 1,918評(píng)論 0 5
  • 當(dāng)一個(gè)系統(tǒng)訪問(wèn)量上來(lái)的時(shí)候,不只是數(shù)據(jù)庫(kù)性能瓶頸問(wèn)題了,數(shù)據(jù)庫(kù)數(shù)據(jù)安全也會(huì)浮現(xiàn),這時(shí)候合理使用數(shù)據(jù)庫(kù)鎖機(jī)制就顯得異...
    初來(lái)的雨天閱讀 3,594評(píng)論 0 22
  • 文/閱先生 尹志平占有了小龍女的初夜,可是金庸筆下的尹志平并不壞,只是令人討厭。但對(duì)很多讀者來(lái)說(shuō),尹志平的令人討厭...
    岳鮮閱讀 7,548評(píng)論 2 6
  • 清晨,太陽(yáng)己暖暖地曬到了床邊。因?yàn)殡p休,所以也懶得起床。享受這溫暖而休閑的時(shí)光也是人生的一大樂(lè)趣。 外面偶爾聽...
    食之樂(lè)閱讀 1,093評(píng)論 21 23