亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL中怎么解決幻讀問題

發布時間:2021-08-06 17:25:16 來源:億速云 閱讀:634 作者:Leah 欄目:開發技術

本篇文章給大家分享的是有關MySQL中怎么解決幻讀問題,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

一、什么是幻讀?

  假設我們有表t結構如下,里面的初始數據行為:(0,0,0),(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5)

CREATE TABLE `t`
(
    `id` INT(11) NOT NULL,
    `key`  INT(11) DEFAULT NULL,
    `value`  INT(11) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `value` (`value`)
) ENGINE = InnoDB;
INSERT INTO t
VALUES (0, 0, 0),
       (1, 1, 1),
       (2, 2, 2),
       (3, 3, 3),
       (4, 4, 4),
       (5, 5, 5)

  假設select * from where value=1 for update,只在這一行加鎖(注意這只是假設),其它行不加鎖,那么就會出現如下場景:

MySQL中怎么解決幻讀問題

Session A的三次查詢Q1-Q3都是select * from where value=1 for update,查詢的value=1的所有row。

  • T1:Q1只返回一行(1,1,1);

  • T2:session B更新id=0的value為1,此時表t中value=1的數據有兩行

  • T3:Q3返回兩行(0,0,1),(1,1,1)

  • T4:session C插入一行(6,6,1),此時表t中value=1的數據有三行

  • T5:Q3返回三行(0,0,1),(1,1,1),(6,6,1)

  • T6:session A事物commit。

其中Q3讀到value=1這一樣的現象,就稱之為幻讀,幻讀指的是一個事務在前后兩次查詢同一個范圍的時候,后一次查詢看到了前一次查詢沒有看到的行。

先對“幻讀”做出如下解釋:

  • 在可重復讀隔離級別下,普通的查詢是快照讀,是不會看到別的事務插入的數據的。因此, 幻讀在“當前讀”下才會出現(三個查詢都是for update表示當前讀);

  • 上面session B的修改update結果,被session A之后的select語句用“當前讀”看到,不能稱為幻讀,幻讀僅專指“新插入的行”。

二、幻讀有什么問題?

(1)需要單獨解決

  眾所周知,select ...for update語句就是將相應的數據行鎖住,比如session A在T1時刻的Q1查詢語句:select * from where value=1 for update就是將value=1的數據行鎖住,但顯然如果是上述的場景發生,此時的for update語義被破壞了(并沒有鎖住value=1的數據行)。

  即使把所有的記錄都加上鎖,還是阻止不了新插入的記錄,所以“幻讀”問題要單獨拿出來解決。沒法依靠MVCC或者行鎖機制來解決。這就引出“間隙鎖”,是另外一種加鎖機制。

(2)間隙鎖引發的并發度

  間隙鎖引入以后,可能會導致同樣語句鎖住更大的范圍,這可能就會影響了并發度。具體請看下面介紹

三、如何解決幻讀?

  產生幻讀的原因是,行鎖只能鎖住行,但是新插入記錄這個動作,要更新的是記錄之間的“間隙”。因此,為了解決幻讀問題,InnoDB只好引入新的鎖,也就是間隙鎖(Gap Lock)。

  間隙:比如表中加入6個記錄,0,5,10,15,20,25。則產生7個間隙:

MySQL中怎么解決幻讀問題

  在一行行掃描的過程中,不僅將給行加上了行鎖,還給行兩邊的空隙也加上了間隙鎖。這樣就確保了無法再插入新的記錄。

  間隙鎖和行鎖合稱next-key lock,每個next-key lock是前開后閉區間(間隙鎖開區間,next-key lock前開后閉區間):

  間隙鎖與間隙鎖之間是不存在沖突的,沖突的是往間隙里插入一條記錄。 

MySQL中怎么解決幻讀問題

  表t中是沒有value=7這個數據的,所以Q1加的間隙鎖(1,5),而Q2也是加的這個間隙鎖,兩者不沖突都是為了保護這個間隙不允許插入值。

  在表t初始化后,假設表的數據如下:

MySQL中怎么解決幻讀問題

  如果用select * from for update執行,則會把整個表所有記錄鎖起來,就形成了7個next-key lock,分別是(-∞,0]、(0,2]、(2,4]、(4,6]、(6,8]、(8, 10]、(10, +supremum]

  間隙鎖的引入,可能會導致同樣的語句鎖住更大的范圍,是會影響了并發度

  假設發生如下場景:

MySQL中怎么解決幻讀問題

 則明顯發生了死鎖,分析如下:

  • Q1:執行select …for update語句,由于id=9這一行并不存在,因此會加上間隙鎖 (8,10);

  • Q2:執行select …for update語句,同樣會加上間隙鎖(8,10),間隙鎖之間不會沖突,因 此這個語句可以執行成功;

  • session B 試圖插入一行(9,9,9),被session A的間隙鎖擋住了,只好進入等待;

  • session A試圖插入一行(9,9,9),被session B的間隙鎖擋住了。

  有上述可知間隙鎖的引入,可能會導致同樣語句鎖住更大的范圍,這其實是影響了并發度。

  為了解決幻讀問題可以采用讀可提交隔離級別,間隙鎖是在可重復讀隔離級別下才會生效的。所以如果把隔離級別設置為讀提交的話, 就沒有間隙鎖了。但同時,你要解決可能出現的數據和日志不一致問題,需要把binlog格式設置為row,也就是說采用“RC隔離級別+日志格式binlog_format=row”組合。

以上就是MySQL中怎么解決幻讀問題,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

景宁| 乡城县| 麻城市| 华池县| 东乡| 天峨县| 阿坝县| 通河县| 达尔| 太湖县| 沙河市| 宜宾市| 会昌县| 辽中县| 巴马| 岱山县| 潜江市| 尚义县| 揭东县| 古田县| 班戈县| 睢宁县| 醴陵市| 宜宾市| 巴楚县| 中宁县| 海淀区| 青岛市| 绥滨县| 霍城县| 定安县| 五家渠市| 浮山县| 西吉县| 会理县| 潞西市| 屯昌县| 高淳县| 赤峰市| 海南省| 景东|