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

一文詳解MySQL是如何解決幻讀的

 更新時間:2023年04月19日 10:46:37   作者:肥肥技術(shù)宅  
事務(wù)A按照一定條件進(jìn)行數(shù)據(jù)讀取,期間事務(wù)B插入了相同搜索條件的新數(shù)據(jù),事務(wù)A再次按照原先條件進(jìn)行讀取操作修改時,發(fā)現(xiàn)了事務(wù)B新插入的數(shù)據(jù)稱之為幻讀,這篇文章主要給大家介紹了關(guān)于MySQL是如何解決幻讀的相關(guān)資料,需要的朋友可以參考下

前言

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

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

什么是幻讀?

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

舉個例子:

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

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

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

普通讀

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

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

當(dāng)前讀

當(dāng)前讀讀取的是記錄的最新版本,讀取時會對讀取的記錄進(jìn)行加鎖, 其他事務(wù)就有可能阻塞。加鎖的 SELECT,或者對數(shù)據(jù)進(jìn)行增刪改都會進(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, 但是它們也會先進(jìn)行讀取,而且只能讀取最新版本。

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

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

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

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

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

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

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

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

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

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

也就是說不能讀取“快照”了,因?yàn)槟阋钚聽顟B(tài)的數(shù)據(jù),那么能不能在當(dāng)前讀的時候,對這段區(qū)間都加上鎖,讓別的事務(wù)阻塞,無法插入。因此,MySQLInnoDB引擎為了解決可重復(fù)讀隔離級別使用當(dāng)前讀而造成的幻讀問題,引入了間隙鎖。

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

舉個例子:

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

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

總結(jié)

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

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

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

到此這篇關(guān)于MySQL是如何解決幻讀的的文章就介紹到這了,更多相關(guān)MySQL解決幻讀內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL登錄時出現(xiàn)ERROR 1045: Access denied for user ‘root‘@‘localhost‘ (using password: YES)無法打開解決方法匯總

    MySQL登錄時出現(xiàn)ERROR 1045: Access denied for&

    本文已解決MySQL登錄時出現(xiàn)Access denied for user ‘root‘@‘localhost‘ (using password: YES)無法打開的相關(guān)報(bào)錯問題,并總結(jié)提出了幾種可用解決方案,又遇到同樣問題的朋友可以參考閱讀下本文
    2024-09-09
  • Windows下MySql錯誤代碼1045的解決方法

    Windows下MySql錯誤代碼1045的解決方法

    這篇文章主要介紹了Windows下MySql錯誤代碼1045的解決方法,文中還包含了2個Linux下的解決方法,需要的朋友可以參考下
    2014-06-06
  • MYSQL加密和壓縮函數(shù)詳解以及實(shí)戰(zhàn)(附示例)

    MYSQL加密和壓縮函數(shù)詳解以及實(shí)戰(zhàn)(附示例)

    這篇文章主要給大家介紹了關(guān)于MYSQL加密和壓縮函數(shù)詳解以及實(shí)戰(zhàn)的相關(guān)資料,加密函數(shù)主要用來對數(shù)據(jù)進(jìn)行加密和界面處理,以保證某些重要數(shù)據(jù)不被別人獲取,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • MySQL數(shù)據(jù)庫重命名的快速且安全方法(3種)

    MySQL數(shù)據(jù)庫重命名的快速且安全方法(3種)

    這篇文章主要介紹了MySQL數(shù)據(jù)庫重命名的快速且安全方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 關(guān)于MySQL的時間進(jìn)位問題淺析

    關(guān)于MySQL的時間進(jìn)位問題淺析

    這篇文章主要給大家介紹了關(guān)于MySQL的時間進(jìn)位問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • MySQL橫縱表相互轉(zhuǎn)化操作實(shí)現(xiàn)方法

    MySQL橫縱表相互轉(zhuǎn)化操作實(shí)現(xiàn)方法

    這篇文章主要介紹了MySQL橫縱表相互轉(zhuǎn)化操作,結(jié)合實(shí)例形式分析了MySQL橫縱表相互轉(zhuǎn)化操作基本原理、實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2020-06-06
  • 體驗(yàn)MySQL5.6.25并處理所遇到的問題

    體驗(yàn)MySQL5.6.25并處理所遇到的問題

    本文給大家分享的是將mysql升級到5.6.25版本后所遇到的2個問題的處理解決辦法,有需要的小伙伴可以參考下。
    2015-07-07
  • mysql時間戳格式化函數(shù)from_unixtime使用的簡單說明

    mysql時間戳格式化函數(shù)from_unixtime使用的簡單說明

    mysql中的FROM_UNIXTIME函數(shù)可以數(shù)據(jù)庫中整型類的時間戳格式化為字符串的日期時間格式,下面這篇文章主要給大家介紹了關(guān)于mysql時間戳格式化函數(shù)from_unixtime使用的簡單說明,需要的朋友可以參考下
    2022-08-08
  • MySQL索引下推詳細(xì)

    MySQL索引下推詳細(xì)

    這篇文章主要介紹MySQL索引下推,索引下推(ICP)是針對MySQL使用索引從表中檢索數(shù)據(jù)行的情況的優(yōu)化。下面就來介紹相關(guān)資料,需要的朋友可以參考一下
    2021-10-10
  • MySQL數(shù)據(jù)庫遷移data文件夾位置詳細(xì)步驟

    MySQL數(shù)據(jù)庫遷移data文件夾位置詳細(xì)步驟

    這篇文章主要介紹了MySQL數(shù)據(jù)庫遷移data文件夾詳細(xì)步驟,需要的朋友可以參考下
    2014-03-03

最新評論

嘉禾县| 炉霍县| 无棣县| 建瓯市| 兴海县| 格尔木市| 会东县| 右玉县| 高阳县| 故城县| 张家口市| 绥芬河市| 海安县| 建平县| 吴桥县| 策勒县| 申扎县| 西充县| 古蔺县| 梨树县| 玉树县| 漯河市| 葵青区| 平塘县| 太谷县| 南岸区| 利辛县| 南投市| 瓦房店市| 江源县| 桑日县| 东城区| 安徽省| 墨竹工卡县| 甘南县| 临颍县| 重庆市| 南召县| 樟树市| 勐海县| 临猗县|