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

InnoDB的RR到底有沒有解決幻讀?

數(shù)據(jù)庫 MariaDB
在Repeatable Read隔離級別下,通過MVCC機制解決了快照讀導致的幻讀問題。在該隔離級別下,進行快照讀時僅在第一次進行數(shù)據(jù)查詢,隨后直接讀取快照,因此不會發(fā)生幻讀。

在InnoDB中,Repeatable Read(重復讀)隔離級別通過間隙鎖和MVCC機制解決了大部分的幻讀問題,但并非所有幻讀都能被解決。要徹底解決幻讀,需要使用Serializable(可串行化)隔離級別。

在Repeatable Read隔離級別下,通過間隙鎖解決了部分當前讀導致的幻讀問題。通過添加間隙鎖來鎖定記錄之間的間隙,以防止新數(shù)據(jù)的插入。

在Repeatable Read隔離級別下,通過MVCC機制解決了快照讀導致的幻讀問題。在該隔離級別下,進行快照讀時僅在第一次進行數(shù)據(jù)查詢,隨后直接讀取快照,因此不會發(fā)生幻讀。

然而,若兩個事務操作如下:事務1首先進行快照讀,然后事務2插入一條記錄并提交,在事務1之后通過更新操作這個新插入的記錄,這樣可以成功更新,這就是幻讀的一種情況。

另外一個場景是,若兩個事務的順序為:事務1先進行快照讀,接著事務2插入了一條記錄并提交,在事務1進行當前讀后,再次進行快照讀也會導致幻讀的發(fā)生。

MVCC解決幻讀

MVCC,即多版本并發(fā)控制(Multiversion Concurrency Control),類似于數(shù)據(jù)庫鎖,是一種并發(fā)控制的解決方案。它主要用于解決讀-寫并發(fā)的情況。

我們了解,在MVCC中存在兩種讀取方式:快照讀和當前讀。

快照讀指的是讀取快照數(shù)據(jù),即在生成快照的那一瞬間的數(shù)據(jù)。例如,通常情況下我們使用的普通SELECT語句在不加鎖的情況下就是一種快照讀。

在可重復讀(RC)中,每次讀取都會重新生成一個快照,始終讀取行的最新版本。在可重復讀(RR)中,快照會在事務第一次執(zhí)行SELECT語句時生成,只有在本事務中對數(shù)據(jù)進行更改才會更新快照。

因此,在RR隔離級別下,同一事務中的多次查詢不會檢索到其他事務的更改內(nèi)容,因此能夠解決幻讀問題。

若我們將事務隔離級別設置為RR,由于MVCC的機制,就可以解決幻讀問題。

有這樣一張表:

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,'Paidaxing');
INSERT INTO users(gmt_create,age,name) values(now(),28,'Paidaxing2023');
INSERT INTO users(gmt_create,age,name) values(now(),38,'Paidaxing666');

執(zhí)行如下事務時序:

事務1


SET session TRANSACTION ISOLATION LEVEL REPEATABLE READ;


BEGIN;


SELECT * FROM users WHERE AGE > 10 AND AGE <30;圖片



BEGIN;


INSERT INTO users(gmt_create, age, name) values(now(), 20, 'Paidaxing999');圖片


COMMIT;

SELECT * FROM users WHERE AGE > 10 AND AGE < 30;圖片


可以觀察到,在同一個事務中,兩次查詢的結(jié)果是相同的。在可重復讀(RR)級別下,由于采用了快照讀,第二次查詢實際上是讀取的快照數(shù)據(jù)。

間隙鎖與幻讀

我們已經(jīng)討論了MVCC如何解決了可重復讀(RR)級別下的快照讀造成的幻讀問題,那么在當前讀取(READ COMMITTED)下,如何解決幻讀問題呢?

當前讀取即讀取最新數(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 ...

舉一個下面的例子:

事務1

事務2

SET session TRANSACTION ISOLATION LEVEL REPEATABLE READ;


BEGIN;


SELECT * FROM users WHERE AGE > 10 AND AGE < 30 for update;圖片



BEGIN;


INSERT INTO users(gmt_create, age, name) values(now(), 20, 'Paidaxing999');


阻塞圖片

在可重復讀(RR)級別下,當我們使用SELECT … FOR UPDATE時,會進行鎖定操作。這不僅會對行記錄進行加鎖,還會對記錄之間的間隙進行加鎖,這就是所謂的間隙鎖。

由于記錄之間的間隙被鎖定,事務2的插入操作被阻塞,直到事務1釋放鎖才得以成功執(zhí)行。

由于事務2無法成功插入數(shù)據(jù),因此幻讀現(xiàn)象得以避免。因此,在可重復讀(RR)級別中,通過引入間隙鎖的方式,成功規(guī)避了幻讀現(xiàn)象的發(fā)生。

解決不了的幻讀

前面我們討論了快照讀(無鎖查詢)和當前讀(有鎖查詢)是如何解決幻讀問題的。然而,上面提到的例子并非幻讀的全部情況。

我們知道MVCC只能解決快照讀導致的幻讀問題,那么如果一個事務中發(fā)生了當前讀,在另一個事務插入數(shù)據(jù)前未加間隙鎖,會發(fā)生什么呢?

接下來,我們稍作修改上面的SQL代碼,采用當前讀方式來查詢數(shù)據(jù):

事務1

事務2

SET session TRANSACTION ISOLATION LEVEL REPEATABLE READ;


BEGIN;


SELECT * FROM users WHERE AGE > 10 AND AGE <30;圖片



BEGIN;


INSERT INTO users(gmt_create, age, name) values(now(), 20, 'Paidaxing999');圖片


COMMIT;

SELECT * FROM users WHERE AGE > 10 AND AGE < 30;圖片


SELECT * FROM users WHERE AGE > 10 AND AGE < 30 for update;圖片


在上面的例子中,在事務1中,我們并未在事務剛啟動時立即加鎖,而是進行了一次普通的查詢,隨后事務2成功插入數(shù)據(jù)后,事務1再進行了兩次查詢。

我們觀察到,事務1后兩次查詢的結(jié)果完全不同。在沒有加鎖的情況下,即快照讀時,讀取的數(shù)據(jù)與第一次查詢結(jié)果相同,從而避免了幻讀現(xiàn)象。但第二次查詢執(zhí)行了鎖定操作,即當前讀,因此讀取到的數(shù)據(jù)中包含了其他事務提交的數(shù)據(jù),導致了幻讀的發(fā)生。

倘若您理解了上述例子以及當前讀的概念,您將很容易意識到,下面的這個案例事實上也會導致幻讀的發(fā)生:

事務1

事務2

SET session TRANSACTION ISOLATION LEVEL REPEATABLE READ;


BEGIN;


SELECT * FROM users WHERE AGE > 10 AND AGE <30;圖片



BEGIN;


INSERT INTO users(gmt_create, age, name) values(now(), 20, 'Paidaxing999');圖片


COMMIT;

SELECT * FROM users WHERE AGE > 10 AND AGE <30;圖片


UPDATE users set name = "Paidaxing888" where age = 20;圖片


SELECT * FROM users WHERE AGE > 10 AND AGE <30;圖片


這里產(chǎn)生幻讀的原因和前面的例子實際上是相同的。即,MVCC只能解決快照讀中的幻讀問題,而對于當前讀(例如 SELECT FOR UPDATE、UPDATE、DELETE 等操作)仍會導致幻讀的產(chǎn)生。在同一個事務中同時進行快照讀和當前讀操作時,將導致幻讀的發(fā)生。

UPDATE 語句也屬于當前讀操作,因此它有可能讀取到其他事務提交的結(jié)果。

為何事務1最后一次查詢和倒數(shù)第二次查詢的結(jié)果會不同呢?

原因在于根據(jù)快照讀的定義,在可重復讀級別下,如果在本事務中發(fā)生了數(shù)據(jù)修改,將會更新快照數(shù)據(jù),因此最后一次查詢的結(jié)果也會相應地發(fā)生變化。

如何避免幻讀

了解了幻讀產(chǎn)生的情境以及無法解決的幾種情況后,讓我們總結(jié)一下如何解決幻讀的問題。

首先,若欲徹底解決幻讀問題,在 InnoDB 中唯一可選的隔離級別是 Serializable(可串行化)級別。

圖源:MySQL 8.0 參考手冊圖源:MySQL 8.0 參考手冊

若希望在一定程度上解決或避免幻讀,可考慮使用可重復讀(RR)隔離級別,但讀提交(RC)和讀未提交(RU)級別肯定不可行。

在可重復讀級別中,盡量使用快照讀(無鎖查詢),這樣不僅可以減少鎖沖突、提高并發(fā)度,還能避免幻讀問題的發(fā)生。

在高并發(fā)場景中若必須加鎖,應在事務開始時立即加鎖,這將引入間隙鎖,有效地避免幻讀。

然而,值得注意的是,間隙鎖是引發(fā)死鎖的重要因素,因此在使用時需要謹慎對待。

責任編輯:武曉燕 來源: 碼上遇見你
相關(guān)推薦

2022-12-27 10:02:38

MVCC機制Innodb

2021-08-26 06:58:15

Innodb RR隔離級別

2023-08-09 17:22:30

MVCCMySQL數(shù)據(jù)

2019-05-28 13:50:27

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

2019-12-06 14:50:49

APP錄音隱私

2024-04-24 08:26:35

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

2015-04-09 13:32:16

編程編程前途

2012-09-21 09:16:48

開源云平臺云計算OpenStack C

2024-03-20 08:12:12

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

2022-06-30 08:00:00

MySQL關(guān)系數(shù)據(jù)庫開發(fā)

2024-05-24 11:54:11

2022-02-17 21:13:08

MySQL架構(gòu)體系

2022-07-14 10:00:21

數(shù)據(jù)價值

2021-07-26 10:28:13

MySQL事務隔離

2023-12-27 18:16:39

MVCC隔離級別幻讀

2020-08-11 15:42:39

微軟小冰Cortana

2021-01-20 20:49:31

AI

2023-06-05 00:28:24

MySQL數(shù)據(jù)庫非鎖定讀

2021-11-30 06:56:59

MySQL幻讀查詢

2024-05-13 11:46:33

MySQL數(shù)據(jù)庫
點贊
收藏

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

主站蜘蛛池模板: 成人区一区二区三区 | 自拍偷拍亚洲视频 | 看av网| 亚洲国产精品一区二区久久 | 亚洲欧美激情四射 | 婷婷色在线 | 99色在线 | 久久精品播放 | 国产精品久久久久久久久久三级 | 久久成人激情 | 国产毛片av | 久久精品一区二区 | 干干天天 | 99pao成人国产永久免费视频 | 麻豆a级片 | 97超碰免费| 国产精品久久一区二区三区 | 人人天天操| 三区在线| 久久夜色精品国产 | 午夜精品久久久久久久久久久久久 | 久久毛片| 国产探花在线观看视频 | 日韩一区二区三区视频 | 亚洲精品视频免费看 | 91综合网 | 亚洲综合婷婷 | 中文字幕在线观看国产 | 人人草天天草 | 国产香蕉视频在线播放 | 女女百合av大片一区二区三区九县 | 久久高清 | 久久久久成人精品免费播放动漫 | 国产一区二区三区在线 | 日韩一区二区精品 | 欧美日韩精品 | 日日操操 | 国产精品theporn| 午夜免费视频观看 | 欧美中国少妇xxx性高请视频 | 国产精品国产三级国产播12软件 |