《高性能mysql》這本書中叁幢,在解釋sql標(biāo)準(zhǔn)的隔離等級的時候曼玩,有一些含混窒百,造成理解不清黍判。主要的原因在于理解顷帖,幻讀渤滞,臟讀和不可重復(fù)讀的區(qū)別。在書中妄呕,幻讀,臟讀和不可重復(fù)讀是如下解釋的
臟讀(Dirty Read):事務(wù)可以讀取未提交的數(shù)據(jù)肿孵,被稱為臟讀唠粥。
不可重復(fù)讀(nonrepeatable read):兩次執(zhí)行相同的查詢晤愧,可能會得到不一樣的結(jié)果蛉腌。
-
幻讀(Phantom Read):當(dāng)某個事物在讀取某個范圍的的記錄的時候,另一個事務(wù)又在該范圍內(nèi)插入新的記錄烙丛,當(dāng)之前的事務(wù)再次讀取該范圍的記錄的時候,會產(chǎn)生幻行(Phantom Row)。
我最開始的時候很迷惑介评,我在想幻讀和不可重復(fù)讀不是一個概念嗎,都是連續(xù)兩次讀取得到的結(jié)果不一樣寒瓦。
事實上不可重復(fù)讀是包含幻讀的概念的。
幻讀是你的查詢語句是試圖獲取一個范圍內(nèi)的數(shù)據(jù)杂腰,注意是一個范圍的數(shù)據(jù)椅文,加入第一次的時候試圖獲取的范圍包含a,b,c,第二次讀取的時候其它事務(wù)添加了數(shù)據(jù)d皆刺,而d也滿足你的查詢范圍,所以第二次查詢的時候漓帅,會試圖去獲取a,b,c,d。這種情況就叫做幻讀忙干。
而不可重復(fù)讀在幻讀的基礎(chǔ)上浪藻,還包含一種情況,就是當(dāng)你讀取指定行的數(shù)據(jù)爱葵,兩次讀取可能會不一樣末融。舉例說明:假如第一次你試圖獲取a,b,c勾习,第二次依舊試圖獲取a,b,c。但是在第二次試圖獲取a,b,c的時候巧婶,可能會發(fā)生兩種情況涂乌,第一個是b沒有,被其它事務(wù)刪除了湾盒,第二是c的內(nèi)容被改變。
以上就是幻讀和不可重復(fù)讀的區(qū)別毅人。
下面貼上sql標(biāo)準(zhǔn)對四種隔離等級的定義
Read Uncommited (未提交讀):事務(wù)中的修改尖殃,即使沒有提交,對其它事務(wù)也都是可見的送丰,事務(wù)可以讀取未提交的數(shù)據(jù)。
Read Committed(提交讀):一個事務(wù)在提交之前俐载,所做的任何修改對其它事務(wù)都是不可見的登失。但是當(dāng)其它事務(wù)修改數(shù)據(jù)的時候,可能會造成兩次讀取的結(jié)果不一樣壁畸。故提交讀存在不可重復(fù)讀的現(xiàn)狀。
Repeatable Read(可重復(fù)讀):該級別保證統(tǒng)一事務(wù)讀取同樣記錄的結(jié)果一致太抓。但是當(dāng)出現(xiàn)讀取一定范圍的記錄的時候令杈,會因為其它事務(wù)在該事務(wù)提交之前插入數(shù)據(jù),導(dǎo)致讀取新插入的數(shù)據(jù)逗噩。產(chǎn)生幻讀跌榔。
-
Serializable (可串行化):強制事務(wù)串行的執(zhí)行僧须,并發(fā)性能最低,但是避免了上述的問題担平。
額外說明:很多博客提出說repeatble read解決了幻讀的問題锭部,這是錯誤,實際上應(yīng)該說mysql的InnoDB和部分引擎通過使用MVCC (Multiversion Concurrency Control 多版本并發(fā)控制)技術(shù)取胎,實現(xiàn)了在提交讀級別的解決幻讀問題的方案湃窍。當(dāng)然這個辦法犧牲的是空間。
參考:
《高性能mysql》第三版坝咐,電子工業(yè)出版社墨坚,Baron Schwartz等著
你若盛開的博客-標(biāo)準(zhǔn)SQL規(guī)范中定義的四個事務(wù)隔離級別