偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

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

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

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

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

另外一個(gè)場(chǎng)景是,若兩個(gè)事務(wù)的順序?yàn)椋菏聞?wù)1先進(jìn)行快照讀,接著事務(wù)2插入了一條記錄并提交,在事務(wù)1進(jìn)行當(dāng)前讀后,再次進(jìn)行快照讀也會(huì)導(dǎo)致幻讀的發(fā)生。

MVCC解決幻讀

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

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

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

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

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

若我們將事務(wù)隔離級(jí)別設(shè)置為RR,由于MVCC的機(jī)制,就可以解決幻讀問題。

有這樣一張表:

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í)行如下事務(wù)時(shí)序:

事務(wù)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;圖片


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

間隙鎖與幻讀

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

當(dāng)前讀取即讀取最新數(shù)據(jù),因此,鎖定的SELECT語句,或者進(jìn)行數(shù)據(jù)的插入、刪除、更新都屬于當(dāng)前讀取操作,例如:

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 ...

舉一個(gè)下面的例子:

事務(wù)1

事務(wù)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');


阻塞圖片

在可重復(fù)讀(RR)級(jí)別下,當(dāng)我們使用SELECT … FOR UPDATE時(shí),會(huì)進(jìn)行鎖定操作。這不僅會(huì)對(duì)行記錄進(jìn)行加鎖,還會(huì)對(duì)記錄之間的間隙進(jìn)行加鎖,這就是所謂的間隙鎖。

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

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

解決不了的幻讀

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

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

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

事務(wù)1

事務(wù)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;圖片


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

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

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

事務(wù)1

事務(wù)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)生幻讀的原因和前面的例子實(shí)際上是相同的。即,MVCC只能解決快照讀中的幻讀問題,而對(duì)于當(dāng)前讀(例如 SELECT FOR UPDATE、UPDATE、DELETE 等操作)仍會(huì)導(dǎo)致幻讀的產(chǎn)生。在同一個(gè)事務(wù)中同時(shí)進(jìn)行快照讀和當(dāng)前讀操作時(shí),將導(dǎo)致幻讀的發(fā)生。

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

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

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

如何避免幻讀

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

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

圖源:MySQL 8.0 參考手冊(cè)圖源:MySQL 8.0 參考手冊(cè)

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

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

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

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

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

2022-12-27 10:02:38

MVCC機(jī)制Innodb

2021-08-26 06:58:15

Innodb RR隔離級(jí)別

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

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

2015-04-09 13:32:16

編程編程前途

2012-09-21 09:16:48

開源云平臺(tái)云計(jì)算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ù)價(jià)值

2021-07-26 10:28:13

MySQL事務(wù)隔離

2023-12-27 18:16:39

MVCC隔離級(jí)別幻讀

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ù)庫
點(diǎn)贊
收藏

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