最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文深入探討MySQL是如何解決幻讀問題

 更新時(shí)間:2023年07月16日 10:21:05   作者:JAVA旭陽  
SQL標(biāo)準(zhǔn)中定義了4種隔離級(jí)別,分別是讀未提交、讀已提交、可重復(fù)讀以及序列化。不同的隔離級(jí)別下,本文將重點(diǎn)探討下MySQL是如何解決幻讀問題的,需要的朋友可以跟著小編一起來探討一下

前言

SQL標(biāo)準(zhǔn)中定義了4種隔離級(jí)別,分別是讀未提交、讀已提交、可重復(fù)讀以及序列化。不同的隔離級(jí)別下,可以解決不同的并發(fā)問題,如下圖所示。當(dāng)然MySQL也基本遵循了這個(gè)標(biāo)準(zhǔn),但是在實(shí)現(xiàn)上稍有不同。

本文重點(diǎn)探討下MySQL是如何解決幻讀問題的,首先串行化隔離級(jí)別鐵定是可以解決所有的并發(fā)問題,相當(dāng)于每個(gè)事務(wù)按順序執(zhí)行,但是性能很差,不是本文重點(diǎn)討論對象。實(shí)際上MySQL默認(rèn)的事務(wù)隔離級(jí)別是可重復(fù)讀,難道這種隔離級(jí)別下MySQL就不管幻讀問題了嗎?其實(shí)不是的,本文就帶大家一起看看MySQL在可重復(fù)讀隔離級(jí)別下是如何解決幻讀問題的。

什么是幻讀?

幻讀是指一個(gè)事務(wù)中按照某個(gè)條件先后兩次讀取數(shù)據(jù)庫,兩次讀取結(jié)果的條數(shù)不同,更加強(qiáng)調(diào)的是讀到了之前沒有讀到的數(shù)據(jù),這種現(xiàn)象稱為幻讀。

舉個(gè)例子:

  • 事務(wù)A一開始只讀取到‘張三’的數(shù)據(jù)記錄。
  • 然后另外一個(gè)事務(wù)B插入了‘趙六’的數(shù)據(jù)記錄。
  • 事務(wù)A再次讀取,發(fā)現(xiàn)了‘張三’、‘趙六’兩條數(shù)據(jù),明明同一個(gè)事務(wù),同樣的查詢條件,前后兩次讀取,多了一條記錄,相當(dāng)于“幻影”,這種情況就是幻讀。

什么是普通讀和當(dāng)前讀?

其實(shí)讀這個(gè)操作也有兩種情況,一種是普通讀,就像上面例子的那樣,還有一種就是當(dāng)前讀。不同的讀模式,MySQL在可重復(fù)讀隔離級(jí)別下的實(shí)現(xiàn)方式也是不一樣的。

普通讀

普通讀又叫快照讀,也就是利用MVCC機(jī)制讀取快照中的數(shù)據(jù)。不加鎖的簡單的SELECT 都屬于快照讀,比如這樣:

SELECT * FROM user WHERE ...
  • 快照讀是基于MVCC實(shí)現(xiàn)的,提高了并發(fā)的性能,降低開銷
  • 大部分業(yè)務(wù)代碼中的讀取都屬于快照讀

當(dāng)前讀

當(dāng)前讀讀取的是記錄的最新版本,讀取時(shí)會(huì)對讀取的記錄進(jìn)行加鎖, 其他事務(wù)就有可能阻塞。加鎖的 SELECT,或者對數(shù)據(jù)進(jìn)行增刪改都會(huì)進(jìn)行當(dāng)前讀。比如:

SELECT * FROM user LOCK IN SHARE MODE; # 共享鎖
SELECT * FROM user FOR UPDATE; # 排他鎖
INSERT INTO user values ... # 排他鎖
DELETE FROM user WHERE ... # 排他鎖
UPDATE user SET ... # 排他鎖
  • update、delete、insert語句雖然沒有select, 但是它們也會(huì)先進(jìn)行讀取,而且只能讀取最新版本。

那不同的讀模式下,MySQL分別是如何避免幻讀的呢?請接著往下看。

普通讀是如何避免幻讀的?

MySQL在可重復(fù)讀隔離級(jí)別下,是通過MVCC機(jī)制避免幻讀的。

MVCC機(jī)制,可以簡單理解成在事務(wù)啟動(dòng)的時(shí)候?qū)?shù)據(jù)庫拍了個(gè)“快照”,它保留了那個(gè)時(shí)刻數(shù)據(jù)庫的數(shù)據(jù)狀態(tài),那么這個(gè)事務(wù)后續(xù)的讀取都可以從這個(gè)“快照”中獲取,哪怕其他事務(wù)新加了數(shù)據(jù),也不會(huì)影響到“快照”中的數(shù)據(jù),也就不會(huì)出現(xiàn)幻讀了。

  • 事務(wù)A在啟動(dòng)的時(shí)候創(chuàng)建了一個(gè)“快照”,查詢出結(jié)果“小紅,小藍(lán)”
  • 后續(xù)事務(wù)B插入一條記錄“小飛”,提交
  • 然后事務(wù)A再次同樣查詢條件查詢,它會(huì)使用“快照”讀取,所以還是“小紅,小藍(lán)”

小結(jié): 針對快照讀(普通 select 語句),是通過 MVCC 方式解決了幻讀。

當(dāng)前讀是如何避免幻讀的?

普通讀(快照讀)實(shí)際上讀取的是歷史版本中的數(shù)據(jù),但一直用這種方式讀取在某些場景下是有問題的。

假設(shè)你要 update 一個(gè)記錄,但是另一個(gè)事務(wù)已經(jīng) delete 這條記錄并且提交事務(wù)了,這樣不是會(huì)產(chǎn)生沖突嗎,所以 update 的時(shí)候肯定要知道最新的數(shù)據(jù)。也就是要做當(dāng)前讀

那么針對當(dāng)前讀,MySQL在可重復(fù)讀隔離級(jí)別下是如何避免幻讀的呢?

也就是說不能讀取“快照”了,因?yàn)槟阋钚聽顟B(tài)的數(shù)據(jù),那么能不能在當(dāng)前讀的時(shí)候,對這段區(qū)間都加上鎖,讓別的事

表中有一個(gè)范圍 id 為(3,5)間隙鎖,那么其他事務(wù)就無法插入 id = 4 這條記錄了,這樣就有效的防止幻讀現(xiàn)象的發(fā)生。

舉個(gè)例子:

  • 事務(wù)A的for_update是屬于當(dāng)前讀,它會(huì)對鎖定 id 范圍 (2, +∞] ,相當(dāng)于理解是間隙鎖。
  • 事務(wù)B插入了id=5的數(shù)據(jù),(2, +∞]范圍被鎖定了,所以無法插入,阻塞。
  • 通過這種加鎖阻塞的方式,也可以避免幻讀。

小結(jié): 針對當(dāng)前讀(select ... for update 等語句),是通過 next-key lock(記錄鎖+間隙鎖)方式解決了幻讀。

總結(jié)

MySQL默認(rèn)采用的隔離級(jí)別是可重復(fù)讀,在這種隔離級(jí)別下不同的讀模式,針對幻讀問題采用了不同解決方案:

  • 針對快照讀(普通 select 語句),是通過 MVCC 方式解決了幻讀。
  • 針對當(dāng)前讀(select ... for update 等語句),是通過 next-key lock(記錄鎖+間隙鎖)方式解決了幻讀。

但是,強(qiáng)調(diào)一點(diǎn)的是,MySQL在可重復(fù)讀級(jí)別下,并沒有完完全全的解決幻讀問題,特別是在一個(gè)事務(wù)的快照讀和當(dāng)前讀穿插使用的場景下,還是會(huì)出現(xiàn)幻讀的情況,比如下圖所示。

以上就是一文深入探討MySQL是如何解決幻讀問題的詳細(xì)內(nèi)容,更多關(guān)于MySQL解決幻讀問題的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL大表中重復(fù)字段的高效率查詢方法

    MySQL大表中重復(fù)字段的高效率查詢方法

    MySQL大表重復(fù)字段應(yīng)該如何查詢到呢?這是很多人都遇到的問題,下面就教您一個(gè)MySQL大表重復(fù)字段的查詢方法,供您參考
    2012-12-12
  • MySQL字段值如何區(qū)分大小寫問題

    MySQL字段值如何區(qū)分大小寫問題

    這篇文章主要介紹了MySQL字段值如何區(qū)分大小寫問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 去掉mysql連接時(shí)報(bào)警聲音的方法

    去掉mysql連接時(shí)報(bào)警聲音的方法

    這篇文章主要介紹了去掉mysql連接時(shí)報(bào)警聲音的方法,本文直接給出設(shè)置命令和參數(shù),其中起作用的就是1個(gè)-p參數(shù),需要的朋友可以參考下
    2015-01-01
  • 深入理解MySQL分區(qū)表的使用

    深入理解MySQL分區(qū)表的使用

    本文主要介紹了深入理解MySQL分區(qū)表的使用
    2024-03-03
  • 檢查并修復(fù)mysql數(shù)據(jù)庫表的具體方法

    檢查并修復(fù)mysql數(shù)據(jù)庫表的具體方法

    這篇文章介紹了檢查并修復(fù)mysql數(shù)據(jù)庫表的具體方法,有需要的朋友可以參考一下
    2013-09-09
  • 詳解MySQL中的pid與socket

    詳解MySQL中的pid與socket

    不知道你有沒有注意過,MySQL 啟動(dòng)時(shí)需要配置 pid 及 socket 文件路徑。偶爾還會(huì)出現(xiàn)因 pid 文件找不到而啟動(dòng)失敗的現(xiàn)象,那么 pid 與 socket 文件究竟是干什么用的呢?我們一起來看下本篇文章。
    2021-06-06
  • 圖文詳解MySQL中兩表關(guān)聯(lián)的連接表如何創(chuàng)建索引

    圖文詳解MySQL中兩表關(guān)聯(lián)的連接表如何創(chuàng)建索引

    這篇文章通過圖文給大家介紹了關(guān)于MySQL中兩表關(guān)聯(lián)的連接表如何創(chuàng)建索引的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-05-05
  • Java項(xiàng)目中mysql深度分頁解決方案大全

    Java項(xiàng)目中mysql深度分頁解決方案大全

    深度分頁的優(yōu)化核心在于減少M(fèi)ySQL掃描的數(shù)據(jù)量,避免全表掃描,通過使用索引、游標(biāo)分頁、延遲關(guān)聯(lián)等技術(shù),可以顯著提升分頁查詢的性能,這篇文章主要介紹了Java項(xiàng)目中mysql深度分頁的相關(guān)資料,需要的朋友可以參考下
    2026-01-01
  • mysql使用insert into select插入查出的數(shù)據(jù)

    mysql使用insert into select插入查出的數(shù)據(jù)

    這篇文章主要介紹了mysql使用insert into select插入查出的數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • MySQL之存儲(chǔ)過程與函數(shù)用法及說明

    MySQL之存儲(chǔ)過程與函數(shù)用法及說明

    文章簡要介紹了MySQL存儲(chǔ)過程和函數(shù)的基本概念、創(chuàng)建方法及調(diào)用方式,重點(diǎn)講解了存儲(chǔ)過程的的創(chuàng)建、調(diào)用、參數(shù)傳遞、變量定義、光標(biāo)、流程控制及常用內(nèi)置函數(shù)等,并提供了創(chuàng)建示例,對于每個(gè)概念和語法,都給出了相應(yīng)的代碼示例和解釋
    2026-05-05

最新評(píng)論

安溪县| 孝义市| 安达市| 大宁县| 仙居县| 墨玉县| 武隆县| 烟台市| 右玉县| 右玉县| 汕尾市| 扬中市| 时尚| 惠来县| 景德镇市| 鄱阳县| 奈曼旗| 青川县| 普兰县| 贞丰县| 岚皋县| 扎鲁特旗| 安仁县| 女性| 巴彦淖尔市| 崇仁县| 金湖县| 保康县| 虎林市| 响水县| 剑川县| 呈贡县| 宣城市| 涞水县| 盐源县| 内黄县| 巢湖市| 察隅县| 忻州市| 怀远县| 彰化县|