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

InnoDB解決幻讀的方法詳解

 更新時間:2023年04月06日 08:26:15   作者:mghio  
這篇文章主要介紹了InnoDB解決幻讀的方法詳解的相關(guān)資料,需要的朋友可以參考下

前言

大部分人在日常的業(yè)務(wù)開發(fā)中,其實(shí)很少去關(guān)注數(shù)據(jù)庫的事務(wù)相關(guān)問題,基本上都是 CURD 一把梭。正好最近在看 MySQL 的相關(guān)基礎(chǔ)知識,其中對于幻讀問題之前一直沒有理解深刻,今天就來聊聊「InnoDB 是如何解決幻讀的」,話不多說,下面進(jìn)入主題。

事務(wù)隔離級別

事務(wù)隔離是數(shù)據(jù)庫處理的基礎(chǔ)之一,是 ACID 中的 I。在 MySQL 的 InnoDB 引擎中支持在 SQL:1992 標(biāo)準(zhǔn)中的四種事務(wù)隔離級別,如下圖所示,其中 P1 表示臟讀(Dirty read),P2 表示不可重復(fù)讀(Dirty read),P3 表示幻讀(Phantom)。

為什么需要定義這么多隔離呢?從上圖中也能猜出一二了,InnoDB 提供多個隔離級別主要原因是:讓使用者可以在多個事務(wù)同時進(jìn)行更改和執(zhí)行查詢時微調(diào)性能與結(jié)果的可靠性、一致性和可再現(xiàn)性之間的平衡的設(shè)置。是一種性能與結(jié)果可靠性間的 trade off。

什么是幻讀

在聊「InnoDB 解決幻讀方式」前我們需要先了解幻讀是什么,官方文檔的描述如下:

A row that appears in the result set of a query, but not in the result set of an earlier query.

其中我加粗的「result set」是關(guān)鍵的地方,兩次查詢返回的是結(jié)果集,說明必須是一個范圍查詢操作。總結(jié)下,幻讀就是:在同一個事務(wù)中,在前后兩次查詢相同范圍時,兩次查詢得到的結(jié)果是不一致的。所以幻讀會產(chǎn)生數(shù)據(jù)一致性問題。

InnoDB 解決幻讀方式

為了解決上述的幻讀問題,InnoDB 引入了兩種鎖,分別是「間隙鎖」和「next-key 鎖」。下面通過一個示例來描述這兩種鎖的作用分別是什么。假如存在一個這樣的 B+ Tree 的索引結(jié)構(gòu),結(jié)構(gòu)中有 4 個索引元素分別是:9527、9530、9535、9540。

此時當(dāng)我們使用如下 SQL 通過主鍵索引查詢一條記錄,并且加上 X 鎖(排它鎖)時:

select * from user where id = 9527 for update; 

這時就會產(chǎn)生一個記錄鎖(也就是行鎖),鎖定 id = 9527 這個索引。

在被鎖定的記錄(這里是 id = 9527)的鎖釋放之前,其它事務(wù)無法對這條被鎖定記錄做任何操作。再回憶一下,前面說的幻讀定義「在同一個事務(wù)中,在前后兩次查詢相同范圍時,兩次查詢得到的結(jié)果是不一致」。注意,這里強(qiáng)調(diào)的是范圍查詢。

InnoDB 要解決幻讀問題,就必須得保證在如果在一個事務(wù)中,通過如下這條語句進(jìn)行鎖定時:

select * from user where id > 9530 and id < 9535 for update; 

此時,另外一個語句再執(zhí)行一如下這條 insert 語句時,需要被阻塞,直到上面這個獲得鎖的事務(wù)釋放鎖后才能執(zhí)行。

insert into user(id, name, age) values(9533, 'Jack', 44); 

為此,InnoDB 引入了「間隙鎖」,它的主要功能是鎖定一段范圍內(nèi)的索引記錄。比如上面查詢 id > 9530 and id < 9535 的時候,對 B+ Tree 中的(9530,9535)這個開區(qū)間范圍的索引加間隙鎖。

在這種加了間隙鎖的情況下,其它事務(wù)對這個區(qū)間的數(shù)據(jù)進(jìn)行插入、更新、刪除都會被鎖住直到這個獲取到鎖的事務(wù)釋放。

這種是在區(qū)間之間的情況,你可能想到另外的一種情況:鎖定多個區(qū)間,如下的一條語句:

select * from user where id > 9530 for update; 

上面這條查詢語句是針對 id > 9530 這個條件加鎖,那么此時它需要鎖定多個索引區(qū)間,所以在這種情況下 InnoDB 引入了「next-key 鎖」機(jī)制。其實(shí) next-key 鎖的效果相當(dāng)于間隙鎖和記錄鎖的合集,記錄鎖鎖定存在的記錄行,間隙鎖鎖住記錄行之間的間隙,而 next-key 鎖它鎖住的是兩者之和。

在 InnoDB 中,每個數(shù)據(jù)行上的非唯一索引列上都會存在一把 next-key 鎖,當(dāng)某個事務(wù)持有該數(shù)據(jù)行的 next-key 鎖時,會鎖住一段左開右閉區(qū)間的數(shù)據(jù)。因此,當(dāng)通過 id > 9530 這樣一種范圍查詢加鎖時,會加 next-key 鎖,鎖定區(qū)間是范圍是:

(9530,9535] (9535,9540] (9540,+∞]

間隙鎖(也叫 Gap 鎖)和 next-key 鎖的區(qū)別在于加鎖的范圍,間隙鎖只鎖定兩個索引之間的引用間隙,而 next-key 鎖會鎖定多個索引區(qū)間,它包含「記錄鎖」和「間隙鎖」。所以,當(dāng)我們使用了范圍查詢,不僅僅命中了已存在的 Record 記錄,還包含了 Gap 間隙。

總結(jié)

雖然在 InnoDB 引擎中通過間隙鎖和 next-key 鎖的方式解決了幻讀問題,但是加鎖之后會影響到數(shù)據(jù)庫的并發(fā)性能,因此,如果對性能要求較高的業(yè)務(wù)場景中,建議把隔離級別設(shè)置成 RC(READ COMMITTED),這個級別中不存在間隙鎖,但是需要考慮到幻讀問題會導(dǎo)致的數(shù)據(jù)一致性。

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

相關(guān)文章

  • mysql 5.7.18 winx64密碼修改

    mysql 5.7.18 winx64密碼修改

    這篇文章主要介紹了mysql 5.7.18 winx64安裝完成后如何對密碼進(jìn)行修改,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • mysql多版本并發(fā)控制MVCC的實(shí)現(xiàn)

    mysql多版本并發(fā)控制MVCC的實(shí)現(xiàn)

    這篇文章主要介紹了mysql多版本并發(fā)控制MVCC的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • MySQL 查找價格最高的圖書經(jīng)銷商的幾種SQL語句

    MySQL 查找價格最高的圖書經(jīng)銷商的幾種SQL語句

    不同的圖書,在不同的經(jīng)銷商的價格不同,我們這里要找到每種圖書最高的經(jīng)銷商是誰? 找最低的類似了。
    2009-07-07
  • Mybatis報錯: org.apache.ibatis.exceptions.PersistenceException解決辦法

    Mybatis報錯: org.apache.ibatis.exceptions.PersistenceException

    這篇文章主要介紹了Mybatis報錯: org.apache.ibatis.exceptions.PersistenceException解決辦法的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • 深入理解MySQL公共表表達(dá)式

    深入理解MySQL公共表表達(dá)式

    公用表達(dá)式是MySQL8.0的新特性,它是一個命名的臨時結(jié)果集,作用范圍是當(dāng)前語句,本文主要介紹了MySQL公共表表達(dá)式使用,感興趣的可以了解一下
    2024-09-09
  • Mysql 實(shí)現(xiàn)向上遞歸查找父節(jié)點(diǎn)并返回樹結(jié)構(gòu)的示例代碼

    Mysql 實(shí)現(xiàn)向上遞歸查找父節(jié)點(diǎn)并返回樹結(jié)構(gòu)的示例代碼

    通過mysql 8.0以下版本實(shí)現(xiàn),一個人多角色id,一個角色對應(yīng)某個節(jié)點(diǎn)menu_id,根節(jié)點(diǎn)的父節(jié)點(diǎn)存儲為NULL, 向上遞歸查找父節(jié)點(diǎn)并返回樹結(jié)構(gòu),今天通過本文給大家介紹Mysql遞歸查找父節(jié)點(diǎn)并返回樹結(jié)構(gòu),感興趣的朋友一起看看吧
    2022-09-09
  • Windows下通過DOS命令登錄MYSQL的方法

    Windows下通過DOS命令登錄MYSQL的方法

    這篇文章主要介紹了Windows下通過DOS命令登錄MYSQL的方法,方法很簡單,本文給出了詳細(xì)操作步驟,需要的朋友可以參考下
    2015-05-05
  • 詳解MySQL的內(nèi)連接和外連接

    詳解MySQL的內(nèi)連接和外連接

    這篇文章主要介紹了詳解MySQL的內(nèi)連接和外連接,mySQL包含兩種聯(lián)接,分別是內(nèi)連接(inner join)和外連接(out join),但我們又同時聽說過左連接,交叉連接等術(shù)語,本文就帶大家來了解一下,需要的朋友可以參考下
    2023-05-05
  • MySQL建表和增添改查操作代碼

    MySQL建表和增添改查操作代碼

    這篇文章主要介紹了MySQL建表和增添改查操作代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-03-03
  • 詳解 MySQL中count函數(shù)的正確使用方法

    詳解 MySQL中count函數(shù)的正確使用方法

    這篇文章主要介紹了 MySQL中count函數(shù)的正確使用方法,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下。
    2020-11-11

最新評論

安新县| 龙南县| 凤冈县| 台江县| 天峻县| 延川县| 广西| 合作市| 宝坻区| 资中县| 德兴市| 太原市| 宁南县| 黄骅市| 洪湖市| 兴海县| 蓝山县| 吉木萨尔县| 阳朔县| 宁阳县| 雷山县| 迭部县| 策勒县| 泽库县| 孟连| 武清区| 灵石县| 乌拉特中旗| 合山市| 蓝田县| 河南省| 长岛县| 襄城县| 虹口区| 定襄县| 贵德县| 锦州市| 金沙县| 临安市| 柳河县| 犍为县|