MySQL實戰(zhàn)45講Day07----事務到底是隔離的還是不隔離的

一洛退、事務的啟動時機:begin/start transaction 命令并不是一個事務的起點毯欣,在執(zhí)行到它們之后的第一個操作InnoDB表的語句(第一個快照讀語句),事務才真正啟動。如果你想要馬上啟動一個事務棕硫,可以使用start transaction with consistent snapshot 這個命令。

二毛甲、在MySQL里年叮,“視圖”的兩個概念:

? ? ? ? 1)一個是view。是一個用查詢語句定義的虛擬表玻募,在調(diào)用的時候執(zhí)行查詢語句并生成結果只损。創(chuàng)建視圖的語法是create view ... ,而它的查詢方法與表一樣七咧。

? ? ? ? 2)一個是InnoDB在實現(xiàn)MVCC時用到的一致性讀視圖跃惫,即consistent read view,用于支持RC(Read Committed艾栋,讀提交)爆存、RR(Repeatable Read,可重復讀)隔離級別的實現(xiàn)蝗砾。

三终蒂、“快照”在MVCC里的工作方式:

????????在可重復讀隔離級別下,事務在啟動的時候就“拍了個快照”遥诉。注意拇泣,這個快照是基于整庫的。InnoDB里面每個事務有一個唯一的事務ID矮锈,叫作transaction id霉翔。它是在事務開始的時候向InnoDB的事務系統(tǒng)申請的,是按申請順序嚴格遞增的苞笨。而每行數(shù)據(jù)也都是有多個版本的债朵。每次事務更新數(shù)據(jù)的時候,都會生成一個新的數(shù)據(jù)版本瀑凝,并且把transaction id賦值給這個數(shù)據(jù)版本的事務ID序芦,記為row trx_id戚哎。同時半醉,舊的數(shù)據(jù)版本要保留,并且在新的數(shù)據(jù)版本中林艘,能夠有信息可以直接拿到它寥枝。也就是說宪塔,數(shù)據(jù)表中的一行記錄,其實可能有多個版本(row)囊拜,每個版本有自己的row trx_id某筐。而每種狀態(tài)并不是物理上都是真實存在的,只記錄了當前的狀態(tài)冠跷。如果需要之前的狀態(tài)南誊,需要根據(jù)當前版本和undo log計算出來的身诺。而undo log是儲存的是每個版本的數(shù)據(jù)。

四抄囚、InnoDB是怎么定義“100G”的快照的霉赡?

? ??????按照可重復讀的定義,一個事務啟動的時候怠苔,能夠看到所有已經(jīng)提交的事務結果同廉。但是之后仪糖,這個事務執(zhí)行期間柑司,其他事務的更新對它不可見。因此锅劝,一個事務只需要在啟動的時候聲明說攒驰,“以我啟動的時刻為準,如果一個數(shù)據(jù)版本是在我啟動之前生成的故爵,就認玻粪;如果是我啟動以后才生成的,我就不認诬垂,我必須要找到它的上一個版本”劲室。當然,如果“上一個版本”也不可見结窘,那就得繼續(xù)往前找很洋。還有,如果是這個事務自己更新的數(shù)據(jù)隧枫,它自己還是要認的喉磁。在實現(xiàn)上, InnoDB為每個事務構造了一個數(shù)組官脓,用來保存這個事務啟動瞬間协怒,當前正在“活躍”的所有事務ID”氨浚“活躍”指的就是孕暇,啟動了但還沒提交。數(shù)組里面事務ID的最小值記為低水位赤兴,當前系統(tǒng)里面已經(jīng)創(chuàng)建過的事務ID的最大值加1記為高水位芭商。這個視圖數(shù)組和高水位,就組成了當前事務的一致性視圖(read-view)搀缠。而數(shù)據(jù)版本的可見性規(guī)則铛楣,就是基于數(shù)據(jù)的row trx_id和這個一致性視圖的對比結果得到的。這個視圖數(shù)組把所有的row trx_id 分成了幾種不同的情況艺普。

這樣簸州,對于當前事務的啟動瞬間來說鉴竭,一個數(shù)據(jù)版本的row trx_id,有以下幾種可能:

1)如果落在綠色部分岸浑,表示這個版本是已提交的事務或者是當前事務自己生成的搏存,這個數(shù)據(jù)是可見的;

2)如果落在紅色部分矢洲,表示這個版本是由將來啟動的事務生成的璧眠,是肯定不可見的;

3)如果落在黃色部分读虏,那就包括兩種情況:

????a. 若 row trx_id在數(shù)組中责静,表示這個版本是由還沒提交的事務生成的,不可見盖桥;

????b. 若 row trx_id不在數(shù)組中灾螃,表示這個版本是已經(jīng)提交了的事務生成的,可見揩徊。(比低水位大腰鬼,但是在當前事務啟動前,就已經(jīng)提交了)

根據(jù)這個聲明塑荒,系統(tǒng)里面隨后發(fā)生的更新熄赡,就跟這個事務看到的內(nèi)容無關了。因為之后的更新齿税,生成的版本一定屬于上面的2或者3(a)的情況彼硫,而對它來說,這些新的數(shù)據(jù)版本是不存在的偎窘,所以這個事務的快照乌助,就是“靜態(tài)”的了。InnoDB利用了“所有數(shù)據(jù)都有多個版本”的這個特性陌知,實現(xiàn)了“秒級創(chuàng)建快照”的能力他托。

五、分析事務A的語句返回的結果:

mysql> CREATE TABLE `t` (

? `id` int(11) NOT NULL,

? `k` int(11) DEFAULT NULL,

? PRIMARY KEY (`id`)

) ENGINE=InnoDB;

insert into t(id, k) values(1,1),(2,2);

方法一:

假設:

事務A開始前仆葡,系統(tǒng)里面只有一個活躍事務ID是99赏参;

事務A、B沿盅、C的版本號分別是100把篓、101、102腰涧,且當前系統(tǒng)里只有這四個事務韧掩;

三個事務開始前,(1,1)這一行數(shù)據(jù)的row trx_id是90窖铡。

這樣疗锐,事務A的視圖數(shù)組就是[99,100], 事務B的視圖數(shù)組是[99,100,101], 事務C的視圖數(shù)組是[99,100,101,102]坊谁。

第一個有效更新是事務C,把數(shù)據(jù)從(1,1)改成了(1,2)滑臊。這時候口芍,這個數(shù)據(jù)的最新版本的row trx_id是102,而90這個版本已經(jīng)成為了歷史版本雇卷。

第二個有效更新是事務B鬓椭,把數(shù)據(jù)從(1,2)改成了(1,3)。這時候关划,這個數(shù)據(jù)的最新版本(即row trx_id)是101小染,而102又成為了歷史版本。

在事務A查詢的時候祭玉,事務B還沒有提交氧映,但是它生成的(1,3)這個版本已經(jīng)變成當前版本了春畔。但這個版本對事務A必須是不可見的脱货,否則就變成臟讀了。

事務A讀數(shù)據(jù)時律姨,它的視圖數(shù)組是[99,100]振峻。當然了,讀數(shù)據(jù)都是從當前版本讀起的择份。所以扣孟,事務A查詢語句的讀數(shù)據(jù)流程是這樣的:

找到(1,3)的時候,判斷出row trx_id=101荣赶,比高水位大凤价,處于紅色區(qū)域,不可見拔创;

接著利诺,找到上一個歷史版本,一看row trx_id=102剩燥,比高水位大慢逾,處于紅色區(qū)域,不可見灭红;

再往前找侣滩,終于找到了(1,1),它的row trx_id=90变擒,比低水位小君珠,處于綠色區(qū)域,可見娇斑。所以策添,k=1澈段;

這樣執(zhí)行下來,雖然期間這一行數(shù)據(jù)被修改過舰攒,但是事務A不論在什么時候查詢败富,看到這行數(shù)據(jù)的結果都是一致的,所以我們稱之為一致性讀摩窃。

方法二:

一個數(shù)據(jù)版本兽叮,對于一個事務視圖來說,除了自己的更新總是可見以外猾愿,有三種情況:

a.版本未提交鹦聪,不可見;

b.版本已提交蒂秘,但是是在視圖創(chuàng)建后提交的泽本,不可見;

c.版本已提交姻僧,而且是在視圖創(chuàng)建前提交的规丽,可見。

所以撇贺,根據(jù)這個規(guī)則判斷圖的查詢結果赌莺,事務A的查詢語句的視圖數(shù)組是在事務A啟動的時候生成的,這時候:

(1,3)還沒提交松嘶,屬于情況1艘狭,不可見;

(1,2)雖然提交了翠订,但是是在視圖數(shù)組創(chuàng)建之后提交的巢音,屬于情況2,不可見尽超;

(1,1)是在視圖數(shù)組創(chuàng)建之前提交的官撼,可見。所以橙弱。k=1歧寺。

注意:更新數(shù)據(jù)(update)都是先讀后寫的,而這個讀棘脐,只能讀當前的值斜筐,稱為“當前讀”(current read)。(同時蛀缝,select語句如果加鎖顷链,也是當前讀。)也就是說屈梁,在更新數(shù)據(jù)語句之前嗤练,添加了一條查詢語句榛了,而且這條查詢語句直接查詢的是當前的值,不管能否可見煞抬。所以霜大,事務B得到的k=3,而不是2。

六革答、事務的可重復讀的能力的實現(xiàn)方法:

? ??????可重復讀的核心就是一致性讀(consistent read)战坤;而事務更新數(shù)據(jù)的時候,只能用當前讀残拐。如果當前的記錄的行鎖被其他事務占用的話途茫,就需要進入鎖等待。而讀提交的邏輯和可重復讀的邏輯類似溪食,它們最主要的區(qū)別是:

a.在可重復讀隔離級別下囊卜,只需要在事務開始的時候創(chuàng)建一致性視圖,之后事務里的其他查詢都共用這個一致性視圖错沃;

b.在讀提交隔離級別下栅组,每一個語句執(zhí)行前都會重新算出一個新的視圖。

c.對于可重復讀捎废,查詢只承認在事務啟動前就已經(jīng)提交完成的數(shù)據(jù)笑窜;

d.對于讀提交致燥,查詢只承認在語句啟動前就已經(jīng)提交完成的數(shù)據(jù)登疗;

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嫌蚤,隨后出現(xiàn)的幾起案子辐益,更是在濱河造成了極大的恐慌,老刑警劉巖脱吱,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件智政,死亡現(xiàn)場離奇詭異,居然都是意外死亡箱蝠,警方通過查閱死者的電腦和手機续捂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宦搬,“玉大人牙瓢,你說我怎么就攤上這事〖湫#” “怎么了矾克?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長憔足。 經(jīng)常有香客問我胁附,道長酒繁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任控妻,我火速辦了婚禮州袒,結果婚禮上,老公的妹妹穿的比我還像新娘弓候。我一直安慰自己稳析,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布弓叛。 她就那樣靜靜地躺著彰居,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撰筷。 梳的紋絲不亂的頭發(fā)上陈惰,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音毕籽,去河邊找鬼抬闯。 笑死,一個胖子當著我的面吹牛关筒,可吹牛的內(nèi)容都是我干的溶握。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蒸播,長吁一口氣:“原來是場噩夢啊……” “哼睡榆!你這毒婦竟也來了?” 一聲冷哼從身側響起袍榆,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤胀屿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后包雀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宿崭,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年才写,在試婚紗的時候發(fā)現(xiàn)自己被綠了葡兑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡赞草,死狀恐怖讹堤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情房资,我是刑警寧澤蜕劝,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響岖沛,放射性物質發(fā)生泄漏暑始。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一婴削、第九天 我趴在偏房一處隱蔽的房頂上張望廊镜。 院中可真熱鬧,春花似錦唉俗、人聲如沸嗤朴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雹姊。三九已至,卻和暖如春衡楞,著一層夾襖步出監(jiān)牢的瞬間吱雏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工瘾境, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歧杏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓迷守,卻偏偏與公主長得像犬绒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子兑凿,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容