欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前言

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

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

什么是幻讀?

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

舉個例子:

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

什么是普通讀和當前讀?

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

普通讀

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

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

當前讀

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

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, 但是它們也會先進行讀取,而且只能讀取最新版本。

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

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

MySQL在可重復讀隔離級別下,是通過MVCC機制避免幻讀的。

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

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

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

當前讀是如何避免幻讀的?

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

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

那么針對當前讀,MySQL在可重復讀隔離級別下是如何避免幻讀的呢?

也就是說不能讀取“快照”了,因為你要最新狀態(tài)的數(shù)據(jù),那么能不能在當前讀的時候,對這段區(qū)間都加上鎖,讓別的事

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

舉個例子:

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

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

總結

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

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

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

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

相關文章

  • mysql把查詢結果按逗號分割的實現(xiàn)示例

    mysql把查詢結果按逗號分割的實現(xiàn)示例

    使用MySQL數(shù)據(jù)庫的GROUP_CONCAT函數(shù),可以將查詢結果按逗號或其他指定分隔符連接成字符串,這種方法適用于需要匯總數(shù)據(jù)并以字符串形式展示的場景,本文介紹了GROUP_CONCAT函數(shù)的基本用法和注意事項,感興趣的可以了解一下
    2024-09-09
  • node 多種方法連接mysql數(shù)據(jù)庫(最新推薦)

    node 多種方法連接mysql數(shù)據(jù)庫(最新推薦)

    mysql是一個流行的第三方模塊,可以通過npm安裝,在Node.js 中,有多種方法可以連接 MySQL 數(shù)據(jù)庫,本文通過實例代碼講解node 多種方法連接mysql數(shù)據(jù)庫的示例代碼,感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • MySQL 學習總結 之 初步了解 InnoDB 存儲引擎的架構設計

    MySQL 學習總結 之 初步了解 InnoDB 存儲引擎的架構設計

    這篇文章主要介紹了MySQL 學習總結 之 初步了解 InnoDB 存儲引擎的架構設計,文中給大家提到了mysql存儲引擎有哪些,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2020-02-02
  • MySQL安裝starting?the?server失敗的2種解決辦法(推薦!)

    MySQL安裝starting?the?server失敗的2種解決辦法(推薦!)

    MySQL是一個非常強大的關系型數(shù)據(jù)庫,但有些初學者在安裝配置的時候,遇到種種的困難,下面這篇文章主要給大家介紹了關于MySQL安裝starting?the?server失敗的2種解決辦法,需要的朋友可以參考下
    2023-04-04
  • 深入理解SQL的四種連接-左外連接、右外連接、內連接、全連接

    深入理解SQL的四種連接-左外連接、右外連接、內連接、全連接

    本篇文章是對SQL中的四種連接-左外連接、右外連接、內連接、全連接進行了詳細的分析介紹,需要的朋友參考下
    2013-07-07
  • mybatis 模糊查詢的實現(xiàn)方法

    mybatis 模糊查詢的實現(xiàn)方法

    這篇文章主要介紹了mybatis 模糊查詢的實現(xiàn)方法的相關資料,希望通過本文能幫助到大家,讓大家掌握這部分內容,需要的朋友可以參考下
    2017-10-10
  • 關于mysql的時區(qū)問題

    關于mysql的時區(qū)問題

    這篇文章主要介紹了關于mysql的時區(qū)問題,具有很好的參考價值,希望對大家有所幫助,以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家,
    2023-11-11
  • mysql連接查詢中and與where的區(qū)別淺析

    mysql連接查詢中and與where的區(qū)別淺析

    在使用數(shù)據(jù)庫查詢語句時,單表的查詢有時候不能滿足項目的業(yè)務需求,在項目開發(fā)過程中,有很多需求都是要涉及到多表的連接查詢,這篇文章主要給大家介紹了關于mysql連接查詢中and與where區(qū)別的相關資料,需要的朋友可以參考下
    2021-07-07
  • Mysql表創(chuàng)建外鍵報錯解決方案

    Mysql表創(chuàng)建外鍵報錯解決方案

    這篇文章主要介紹了Mysql表創(chuàng)建外鍵報錯解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • mysql 獲取今天、昨天0點時間戳的實例

    mysql 獲取今天、昨天0點時間戳的實例

    今天小編就為大家分享一篇mysql 獲取今天、昨天0點時間戳的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05

最新評論