成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Innodb的RR到底有沒有解決幻讀?看不懂你打我!

開發(fā) 前端
在RR級別中,因為有MVCC機制,對于普通的無鎖查詢,這種是屬于快照讀的,RR的快照讀在同一個事務(wù)中只會讀一次,所以在事務(wù)過程中,其他事務(wù)的變更不會影響到當前事務(wù)的查詢結(jié)果。所以這種幻讀是可以解決的。

關(guān)于Innodb中的REPEATABLE READ這種隔離級別到底有沒有解決幻讀?好像眾說紛紜,大家的說法都不一致。

有的人說,RR當然沒解決幻讀了,因為只有Serializable才能解決幻讀。

也有人說,RR解決了幻讀,因為RR中加了間隙鎖,就能解決幻讀的問題。

還有人說,只有間隙鎖是沒用的,還有MVCC也幫助RR解決了幻讀的問題。

那到底真實情況是怎么樣的呢?

?我認為,InnoDB中的REPEATABLE READ這種隔離級別通過間隙鎖+MVCC解決了大部分的幻讀問題,只有一種特殊的幻讀情況無法解決。

為什么這么說呢?這種特殊情況是怎么回事兒呢?本文就來把這個問題講清楚。(本文中所有SQL的運行環(huán)境是MySQL 5.7.9 及MySQL 8.0.30)?

什么是幻讀

?在介紹如何解決幻讀之前,有必要再明確一下什么是幻讀,確保大家理解是一致的。

幻讀就是事務(wù)在做范圍查詢(SELECT)的過程中,有另外一個事務(wù)對范圍內(nèi)新增了記錄(INSERT),導(dǎo)致范圍查詢的結(jié)果條數(shù)不一致的現(xiàn)象。?

有這樣一張表:?

CREATE TABLE users (    id INT UNSIGNED AUTO_INCREMENT,    gmt_create DATETIME NOT NULL,    age INT NOT NULL,    name VARCHAR(16) NOT NULL,    PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO users(gmt_create,age,name) values(now(),18,'Hollis');INSERT INTO users(gmt_create,age,name) values(now(),28,'HollisChuang');INSERT INTO users(gmt_create,age,name) values(now(),38,'Hollis666');

圖片

接著我們進行如下操作:

圖片

在這個例子中,在事務(wù)1中執(zhí)行了兩次相同的查詢操作。但是兩次操作中間事務(wù)2向數(shù)據(jù)庫中增加了一條符合事務(wù)1的查詢條件的數(shù)據(jù),最終事務(wù)1的兩次查詢得到的結(jié)果是不一樣的,這種現(xiàn)象就是幻讀。

MVCC與幻讀?

MVCC,是Multiversion Concurrency Control的縮寫,翻譯過來是多版本并發(fā)控制,和數(shù)據(jù)庫鎖一樣,他也是一種并發(fā)控制的解決方案。它主要用來解決讀-寫并發(fā)的情況。關(guān)于MVCC的原理可以參考《??再有人問你什么是MVCC,就把這篇文章發(fā)給他!???》

我們知道,在MVCC中有兩種讀,一種是快照讀、一種是當前讀。

所謂快照讀,就是讀取的是快照數(shù)據(jù),即快照生成的那一刻的數(shù)據(jù),像我們常用的普通的SELECT語句在不加鎖情況下就是快照讀。

SELECT * FROM xx_table WHERE ...

在 RC 中,每次讀取都會重新生成一個快照,總是讀取行的最新版本。


在 RR 中,快照會在事務(wù)中第一次SELECT語句執(zhí)行時生成,只有在本事務(wù)中對數(shù)據(jù)進行更改才會更新快照。


那么也就是說,如果在RR下,一個事務(wù)中的多次查詢,是不會查詢到其他的事務(wù)中的變更內(nèi)容的,所以,也就是可以解決幻讀的。

所以,針對上面的例子,如果我們把事務(wù)隔離級別設(shè)置為RR,那么因為有了MVCC的機制,就能解決幻讀的問題:?

圖片

可以看到,同一個事務(wù)中的兩次查詢結(jié)果是一樣的,就是在RR級別下,因為有快照讀,所以第二次查詢其實讀取的是一個快照數(shù)據(jù)。

間隙鎖與幻讀

?上面我們講過了MVCC能解決RR級別下面的快照讀的幻讀問題,那么當前讀下面的幻讀問題怎么解決呢?

當前讀就是讀取最新數(shù)據(jù),所以,加鎖的 SELECT,或者對數(shù)據(jù)進行增刪改都會進行當前讀,比如:?

SELECT * FROM xx_table LOCK IN SHARE MODE;
SELECT * FROM xx_table FOR UPDATE;
INSERT INTO xx_table ...
DELETE FROM xx_table ...
UPDATE xx_table ...

舉一個下面的例子:

圖片

像上面這種情況,在RR的級別下,當我們使用SELECT … FOR UPDATE的時候,會進行加鎖,不僅僅會對行記錄進行加鎖,還會對記錄之間的間隙進行加鎖,這就叫做間隙鎖(參考:??數(shù)據(jù)庫的鎖,到底鎖的是什么????)。因為記錄之間的間隙被鎖住了,所以事務(wù)2的插入操作就被阻塞了,一直到事務(wù)1把鎖釋放掉他才能執(zhí)行成功。

因為事務(wù)2無法插入數(shù)據(jù)成功,所以也就不會存在幻讀的現(xiàn)象了。所以,在RR級別中,通過加入間隙鎖的方式,就避免了幻讀現(xiàn)象的發(fā)生。

解決不了的幻讀

前面我們介紹了快照讀(無鎖查詢)和當前讀(有鎖查詢)下是如何解決幻讀的問題的,但是,上面的例子就是幻讀的所有情況了嗎?顯然并不是。

我們說MVCC只能解決快照讀的幻讀,那如果在一個事務(wù)中發(fā)生了當前讀,并且在另一個事務(wù)插入數(shù)據(jù)前沒來得及加間隙鎖的話,會發(fā)生什么呢?

那么,我們稍加修改一下上面的SQL代碼,通過當前讀的方式進行查詢數(shù)據(jù):

圖片

在上面的例子中,在事務(wù)1中,我們并沒有在事務(wù)開啟后立即加鎖,而是進行了一次普通的查詢,然后事務(wù)2插入數(shù)據(jù)成功之后,再通過事務(wù)1進行了2次查詢。

?我們發(fā)現(xiàn),事務(wù)1后面的兩次查詢結(jié)果完全不一樣,沒加鎖的情況下,就是快照讀,讀到的數(shù)據(jù)就和第一次查詢是一樣的,就不會發(fā)生幻讀。但是第二次查詢加了鎖,就是當前讀,那么讀取到的數(shù)據(jù)就有其他事務(wù)提交的數(shù)據(jù)了,就發(fā)生了幻讀。

那么,如果你理解了上面的這個例子,并且你也理解了當前讀的概念,那么你很容易就能想到,下面的這個CASE其實也是會發(fā)生幻讀的:

圖片

這里發(fā)生幻讀的原理,和上面的例子其實是一樣的,那就是MVCC只能解決快照讀中的幻讀問題,而對于當前讀(SELECT FOR UPDATE、UPDATE、DELETE等操作)還是會產(chǎn)生幻讀的現(xiàn)象的。

UPDATE語句也是一種當前讀,所以它是可以讀到其他事務(wù)的提交結(jié)果的。

為什么事務(wù)1的最后一次查詢和倒數(shù)第二次查詢的結(jié)果也不一樣呢?

是因為根據(jù)快照讀的定義,在RR中,如果本事務(wù)中發(fā)生了數(shù)據(jù)的修改,那么就會更新快照,那么最后一次查詢的結(jié)果也就發(fā)生了變化。

如何避免幻讀

?那么了解了幻讀的解決場景,以及不能解決的幾個CASE之后,我們來總結(jié)一下該如何解決幻讀的問題呢?

首先,如果想要徹底解決幻讀的問題,在InnoDB中只能使用Serializable這種隔離級別。

圖片圖源:MySQL 8.0 Reference Manual

那么,如果想在一定程度上解決或者避免發(fā)生幻讀的話,使用RR也可以,但是RC、RU肯定是不行的。

在RR級別中,能使用快照讀(無鎖查詢)的就使用快照讀,這樣不僅可以減少鎖沖突,提升并發(fā)度,而且還能避免幻讀的發(fā)生。

那么,如果在并發(fā)場景中,一定要加鎖的話怎么辦呢?那就一定要在事務(wù)一開始就立即加鎖,這樣就會有間隙鎖,也能有效的避免幻讀?的發(fā)生。

但是需要注意的是,間隙鎖是導(dǎo)致死鎖的一個重要根源~所以,用起來也需要慎重。?

總結(jié)

在RC級別中,幻讀是沒有辦法解決的,因為RC中快照讀是每一次都會重新生成快照,并且RC中也不會有間隙鎖。

在RR級別中,因為有MVCC機制,對于普通的無鎖查詢,這種是屬于快照讀的,RR的快照讀在同一個事務(wù)中只會讀一次,所以在事務(wù)過程中,其他事務(wù)的變更不會影響到當前事務(wù)的查詢結(jié)果。所以這種幻讀是可以解決的。

當時,MVCC只能對快照讀起作用,而對于加鎖的讀請求,這種屬于當前讀,當前讀的話是可以查詢到其他事務(wù)的變更的,所以會產(chǎn)生幻讀。

?想要解決幻讀,可以使用Serializable這種隔離級別,或者使用RR也能解決大部分的幻讀問題。?

在RR級別下,為了避免幻讀的發(fā)生,要么就是使用快照讀,要么就是在事務(wù)一開始就加鎖。?

責任編輯:姜華 來源: Hollis
相關(guān)推薦

2024-04-25 08:16:06

InnodbReadMVCC

2017-06-16 09:22:22

數(shù)據(jù)結(jié)構(gòu)算法鏈表

2021-08-26 06:58:15

Innodb RR隔離級別

2022-07-26 14:38:08

JavaScriptWeb安全自動化

2023-08-09 17:22:30

MVCCMySQL數(shù)據(jù)

2024-10-14 12:56:28

2019-12-06 14:50:49

APP錄音隱私

2019-05-28 13:50:27

MySQL幻讀數(shù)據(jù)庫

2019-12-09 08:29:26

Netty架構(gòu)系統(tǒng)

2024-04-24 08:26:35

事務(wù)數(shù)據(jù)InnoDB

2012-09-21 09:16:48

開源云平臺云計算OpenStack C

2015-04-09 13:32:16

編程編程前途

2021-12-09 11:59:49

JavaScript前端提案

2022-06-16 14:07:26

Java代碼代碼review

2020-03-30 16:45:06

代碼看不懂

2022-12-12 07:40:36

服務(wù)器項目Serverless

2024-03-20 08:12:12

分庫分表數(shù)據(jù)

2023-06-30 08:01:04

Reactuse關(guān)鍵詞

2024-05-24 11:54:11

2022-02-07 09:05:00

GitHub功能AI
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 色视频网站 | 中文字幕乱码一区二区三区 | 久久久久久国产精品免费免费狐狸 | www.99精品 | 成人免费观看男女羞羞视频 | 国产在线精品一区二区三区 | 亚洲欧美日韩国产综合 | 亚欧午夜| 夜夜操天天操 | 精品国产高清一区二区三区 | 亚洲伊人久久综合 | 日本色高清 | 欧美日一区二区 | 91午夜在线 | 亚洲成人精品在线 | 亚洲国产成人精品久久 | 中文字幕不卡视频在线观看 | 国产一区二区三区色淫影院 | 中文字幕在线视频观看 | 一级黄色夫妻生活 | 伊人看片 | 91精品在线看 | 日韩欧美在线观看 | 日韩a v在线免费观看 | 欧美精品99 | 伦理午夜电影免费观看 | 天天夜碰日日摸日日澡 | 国产亚洲精品久久久久动 | 成人精品 | 一区二区中文 | 精产嫩模国品一二三区 | 久久久久久久一区二区 | 国产一区二区在线视频 | 一区二区三区高清 | 91电影院| 中文字幕第一页在线 | 国产精品不卡 | 久久里面有精品 | 国产精品久久久久久久久久久久冷 | 欧美一级免费片 | 亚洲综合精品 |