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

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

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

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

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

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

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

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

MVCC解決幻讀

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

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

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

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

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

若我們將事務隔離級別設置為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');

執行如下事務時序:

事務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;圖片


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

間隙鎖與幻讀

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

當前讀取即讀取最新數據,因此,鎖定的SELECT語句,或者進行數據的插入、刪除、更新都屬于當前讀取操作,例如:

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釋放鎖才得以成功執行。

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

解決不了的幻讀

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

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

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

事務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成功插入數據后,事務1再進行了兩次查詢。

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

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

事務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;圖片


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

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

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

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

如何避免幻讀

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

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

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

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

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

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

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

責任編輯:武曉燕 來源: 碼上遇見你
相關推薦

2022-12-27 10:02:38

MVCC機制Innodb

2021-08-26 06:58:15

Innodb RR隔離級別

2023-08-09 17:22:30

MVCCMySQL數據

2019-05-28 13:50:27

MySQL幻讀數據庫

2019-12-06 14:50:49

APP錄音隱私

2024-04-24 08:26:35

事務數據InnoDB

2015-04-09 13:32:16

編程編程前途

2012-09-21 09:16:48

開源云平臺云計算OpenStack C

2024-03-20 08:12:12

分庫分表數據

2022-06-30 08:00:00

MySQL關系數據庫開發

2024-05-24 11:54:11

2022-02-17 21:13:08

MySQL架構體系

2022-07-14 10:00:21

數據價值

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數據庫非鎖定讀

2021-11-30 06:56:59

MySQL幻讀查詢

2024-05-13 11:46:33

MySQL數據庫
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久久 | 国产成人精品a视频一区www | 国产精品成人一区二区三区夜夜夜 | 久久国产精品视频免费看 | 日本人爽p大片免费看 | 久久av网 | 伊人艹| 黄色a三级| 久久精品久久久久久 | 亚洲 欧美 日韩 在线 | 欧美在线观看一区 | 中文av电影| 亚洲精品久久久一区二区三区 | 日韩精品一区在线 | 国产免费观看久久黄av片涩av | 中文字幕日韩一区 | 亚洲精品久久久久久久不卡四虎 | 欧美精品成人 | 国产成人精品免费 | 日韩欧美一区二区三区免费观看 | 国产一级淫片a直接免费看 免费a网站 | 亚洲精选一区二区 | 国产高清一区二区三区 | 国产欧美精品一区二区三区 | 日韩欧美在线观看 | 国产露脸国语对白在线 | 亚洲一区二区精品视频在线观看 | 亚洲国产精品suv | 精品欧美一区二区三区精品久久 | 国产精品99久久久久久久vr | 久久久日韩精品一区二区三区 | 亚洲精品在线看 | 天天射天天操天天干 | 久久99精品久久久久久 | 日韩精品一区二区三区免费视频 | 国产精品视频一区二区三区不卡 | 影音av | 白浆在线| 欧美一级特黄aaa大片在线观看 | 国产精品久久午夜夜伦鲁鲁 | 青青久久 |