日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

你了解幻读吗?

發(fā)布時(shí)間:2024/8/5 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 你了解幻读吗? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先我們創(chuàng)建一個(gè)表,并插入測(cè)試數(shù)據(jù):

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

什么是幻讀?

在可重復(fù)讀隔離級(jí)別下,普通的快照讀詩(shī)不會(huì)看到別的事務(wù)插入的數(shù)據(jù)的,因此,幻讀只在“當(dāng)前讀”下才會(huì)出現(xiàn)
幻讀專指新插入的行。修改的數(shù)據(jù)被其他事務(wù)的“當(dāng)前讀”看到,不能稱為幻讀。

幻讀有什么問(wèn)題?

語(yǔ)義:

  如圖:T1時(shí)刻, sessionA的語(yǔ)言是將所有d=5的數(shù)據(jù),加行鎖。T2時(shí)刻,SessionB將id=0這條數(shù)據(jù)改成了d=5,此時(shí)有兩條 d=5的數(shù)據(jù),但是由于第二條數(shù)據(jù)并沒(méi)有加鎖,可以對(duì)其進(jìn)行修改。這就破壞了sessionA里的Q1語(yǔ)句要鎖住所有d=5的行的加鎖聲明。

數(shù)據(jù)一致性:

數(shù)據(jù)一致性不僅指數(shù)據(jù)庫(kù)內(nèi)部數(shù)據(jù)狀態(tài)的一致性,還包含了數(shù)據(jù)和日志在邏輯上的一致性

T6時(shí)刻后,數(shù)據(jù)庫(kù)中的數(shù)據(jù)為:
(5,5,100)
(0,5,5)
(1,5,5)
而bin log里的內(nèi)容如下:

update t set d=5 where id=0; /*(0,0,5)*/
update t set c=5 where id=0; /*(0,5,5)*/

insert into t values(1,1,5); /*(1,1,5)*/
update t set c=5 where id=1; /*(1,5,5)*/

update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/

可以看到id=0和id=1這兩行,發(fā)生了數(shù)據(jù)不一致。

可以看到id=0和id=1這兩行,發(fā)生了數(shù)據(jù)不一致。

InnoDB如何解決幻讀問(wèn)題?

為了解決幻讀的問(wèn)題,InnoDB引入了新的鎖——間隙鎖(Gap Lock)
即將兩個(gè)值之間的空隙進(jìn)行加鎖,比如表t,初始化插入了6個(gè)記錄,這就會(huì)產(chǎn)生7個(gè)空隙

此時(shí),我們執(zhí)行

select * from t where d = 5 for update;

的時(shí)候,就不僅給這已有的6個(gè)記錄加上了行鎖,同時(shí)加了7個(gè)間隙鎖,這樣就保證了無(wú)法再插入新的記錄。
注意:
對(duì)于非索引字段進(jìn)行update或select..for update操作的時(shí)候,代價(jià)極高(上述SQL)。所有記錄上鎖,已經(jīng)所有間隙加鎖
對(duì)于索引字段執(zhí)行上述操作,只有字段本身一級(jí)附近的間隙會(huì)被加鎖。
間隙鎖存在沖突,是“往這個(gè)間隙中插入一個(gè)記錄”這個(gè)操作。
思考一下這是為什么呢?
InnoDB索引是一顆B+樹,同一級(jí)上的節(jié)點(diǎn)是順序排列的,所以只需要鎖住字段本身和附近間隙即可,因?yàn)楹蟛迦氲臄?shù)據(jù)位置是固定的。非索引字段則不具備這樣的結(jié)構(gòu),所以只能采用全表掃描的方式加鎖。

例如:

這里由于表中沒(méi)有c=7這條記錄,并且 c是索引字段,所以SessionA會(huì)在(5,10)這個(gè)間隙上加鎖。而SessionB也是在這個(gè)間隙進(jìn)行加鎖,這兩個(gè)鎖的目的都是為了保護(hù)這個(gè)間隙不被插入數(shù)據(jù),所以他們之間是不沖突的。

間隙鎖和行鎖合城 next-key lock。每個(gè)next-key lock都是前開后閉區(qū)間。

間隙鎖帶來(lái)的問(wèn)題:

例如:

這是一個(gè)間隙鎖導(dǎo)致死鎖的問(wèn)題。

SessionA執(zhí)行更新語(yǔ)句后,由于id=9這一行數(shù)據(jù)不存在,所以會(huì)在(5,10)上加上間隙鎖。
SessionB同理,兩個(gè)間隙鎖不會(huì)沖突。
SessionB試圖插入一行數(shù)據(jù)(0,9,9),被SessionA的間隙鎖擋住,進(jìn)入等待。
SessionA試圖插入一行數(shù)據(jù)(0,9,9),被SessionB的間隙鎖擋住了。
循環(huán)等待,形成死鎖。

間隙鎖的引入,可能會(huì)導(dǎo)致同樣的語(yǔ)句鎖住更大的范圍,這其實(shí)是影響了并發(fā)度的。
那么有沒(méi)有簡(jiǎn)單的方式,去解決幻讀呢?
可以把數(shù)據(jù)庫(kù)的隔離級(jí)別設(shè)置為讀提交,再將bin log的格式設(shè)置為row,這樣可以解決數(shù)據(jù)和日志不一致的問(wèn)題。如果我們的業(yè)務(wù)需求,用讀提交就夠了,不用可重復(fù)度。可以采用這種方法進(jìn)行配置。

總結(jié)

以上是生活随笔為你收集整理的你了解幻读吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。