Mysql的mvcc機制

我們都知道事務(wù)的4個特性,原子性 一致性 隔離性和持久化
事務(wù)具有4個特征遏考,分別是原子性捂人、一致性逐纬、隔離性和持久性蛔屹,簡稱事務(wù)的ACID特性;

一豁生、原子性(atomicity)

一個事務(wù)要么全部提交成功兔毒,要么全部失敗回滾,不能只執(zhí)行其中的一部分操作甸箱,這就是事務(wù)的原子性

二育叁、一致性(consistency)

事務(wù)的執(zhí)行不能破壞數(shù)據(jù)庫數(shù)據(jù)的完整性和一致性,一個事務(wù)在執(zhí)行之前和執(zhí)行之后芍殖,數(shù)據(jù)庫都必須處于一致性狀態(tài)豪嗽。

如果數(shù)據(jù)庫系統(tǒng)在運行過程中發(fā)生故障,有些事務(wù)尚未完成就被迫中斷,這些未完成的事務(wù)對數(shù)據(jù)庫所作的修改有一部分已寫入物理數(shù)據(jù)庫昵骤,這是數(shù)據(jù)庫就處于一種不正確的狀態(tài)树碱,也就是不一致的狀態(tài)

三、隔離性(isolation)

事務(wù)的隔離性是指在并發(fā)環(huán)境中变秦,并發(fā)的事務(wù)時相互隔離的成榜,一個事務(wù)的執(zhí)行不能不被其他事務(wù)干擾。不同的事務(wù)并發(fā)操作相同的數(shù)據(jù)時蹦玫,每個事務(wù)都有各自完成的數(shù)據(jù)空間赎婚,即一個事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對其他并發(fā)事務(wù)時隔離的,并發(fā)執(zhí)行的各個事務(wù)之間不能相互干擾樱溉。

在標準SQL規(guī)范中挣输,定義了4個事務(wù)隔離級別,不同的隔離級別對事務(wù)的處理不同福贞,分別是:未授權(quán)讀取撩嚼,授權(quán)讀取,可重復(fù)讀取和串行化

1挖帘、讀未提交(Read Uncommited)完丽,該隔離級別允許臟讀取,其隔離級別最低拇舀;比如事務(wù)A和事務(wù)B同時進行逻族,事務(wù)A在整個執(zhí)行階段,會將某數(shù)據(jù)的值從1開始一直加到10骄崩,然后進行事務(wù)提交聘鳞,此時,事務(wù)B能夠看到這個數(shù)據(jù)項在事務(wù)A操作過程中的所有中間值(如1變成2要拂,2變成3等)抠璃,而對這一系列的中間值的讀取就是未授權(quán)讀取

2、授權(quán)讀取也稱為已提交讀(Read Commited)脱惰,授權(quán)讀取只允許獲取已經(jīng)提交的數(shù)據(jù)鸡典。比如事務(wù)A和事務(wù)B同時進行,事務(wù)A進行+1操作枪芒,此時彻况,事務(wù)B無法看到這個數(shù)據(jù)項在事務(wù)A操作過程中的所有中間值,只能看到最終的10舅踪。另外纽甘,如果說有一個事務(wù)C,和事務(wù)A進行非常類似的操作抽碌,只是事務(wù)C是將數(shù)據(jù)項從10加到20悍赢,此時事務(wù)B也同樣可以讀取到20决瞳,即授權(quán)讀取允許不可重復(fù)讀取。

3左权、可重復(fù)讀(Repeatable Read)

就是保證在事務(wù)處理過程中皮胡,多次讀取同一個數(shù)據(jù)時,其值都和事務(wù)開始時刻是一致的赏迟,因此該事務(wù)級別禁止不可重復(fù)讀取和臟讀取屡贺,但是有可能出現(xiàn)幻影數(shù)據(jù)。所謂幻影數(shù)據(jù)锌杀,就是指同樣的事務(wù)操作甩栈,在前后兩個時間段內(nèi)執(zhí)行對同一個數(shù)據(jù)項的讀取,可能出現(xiàn)不一致的結(jié)果糕再。在上面的例子中量没,可重復(fù)讀取隔離級別能夠保證事務(wù)B在第一次事務(wù)操作過程中,始終對數(shù)據(jù)項讀取到1突想,但是在下一次事務(wù)操作中殴蹄,即使事務(wù)B(注意,事務(wù)名字雖然相同猾担,但是指的是另一個事務(wù)操作)采用同樣的查詢方式饶套,就可能讀取到10或20;

4垒探、串行化

是最嚴格的事務(wù)隔離級別,它要求所有事務(wù)被串行執(zhí)行怠李,即事務(wù)只能一個接一個的進行處理圾叼,不能并發(fā)執(zhí)行。

四捺癞、持久性(durability)

一旦事務(wù)提交夷蚊,那么它對數(shù)據(jù)庫中的對應(yīng)數(shù)據(jù)的狀態(tài)的變更就會永久保存到數(shù)據(jù)庫中。--即使發(fā)生系統(tǒng)崩潰或機器宕機等故障髓介,只要數(shù)據(jù)庫能夠重新啟動惕鼓,那么一定能夠?qū)⑵浠謴?fù)到事務(wù)成功結(jié)束的狀態(tài)

Mysql的mvcc機制是多版本并發(fā)控制主要是針對innodb的讀已提交和可重復(fù)度,不支持讀未提交和串行化(將所有的操作串行化執(zhí)行唐础,效率低)箱歧。
多版本控制(Multiversion Concurrency Control): 指的是一種提高并發(fā)的技術(shù)。最早的數(shù)據(jù)庫系統(tǒng)一膨,只有讀讀之間可以并發(fā)呀邢,讀寫,寫讀豹绪,寫寫都要阻塞价淌。引入多版本之后,只有寫寫之間相互阻塞,其他三種操作都可以并行蝉衣,這樣大幅度提高了InnoDB的并發(fā)度括尸。在內(nèi)部實現(xiàn)中,InnoDB通過undo log保存每條數(shù)據(jù)的多個版本病毡,并且能夠找回數(shù)據(jù)歷史版本提供給用戶讀濒翻,每個事務(wù)讀到的數(shù)據(jù)版本可能是不一樣的。
Mysql利用mvcc+悲觀鎖和mvcc+樂觀鎖,提高數(shù)據(jù)庫的整體性能mvcc解決讀寫沖突,鎖解決了謝謝沖突剪验。

當前讀和快照讀
? 當前讀
像select lock in share mode(共享鎖), select for update ; update, insert ,delete(排他鎖)這些操作都是一種當前讀肴焊,為什么叫當前讀?就是它讀取的是記錄的最新版本功戚,讀取時還要保證其他并發(fā)事務(wù)不能修改當前記錄娶眷,會對讀取的記錄進行加鎖。
? 快照讀
像不加鎖的select操作就是快照讀啸臀,即不加鎖的非阻塞讀届宠;快照讀的前提是隔離級別不是串行級別,串行級別下的快照讀會退化成當前讀乘粒;之所以出現(xiàn)快照讀的情況豌注,是基于提高并發(fā)性能的考慮,快照讀的實現(xiàn)是基于多版本并發(fā)控制灯萍,即MVCC,可以認為MVCC是行鎖的一個變種轧铁,但它在很多情況下,避免了加鎖操作旦棉,降低了開銷齿风;既然是基于多版本,即快照讀可能讀到的并不一定是數(shù)據(jù)的最新版本绑洛,而有可能是之前的歷史版本救斑。
Mvcc的幾個概念
隱藏字段
(1) 事務(wù)id:DB_TRX_ID,表示最近一次對本記錄行作修改(insert | update)的事務(wù)ID真屯。至于delete操作脸候,InnoDB認為是一個update操作,不過會更新一個另外的刪除位绑蔫,將行表示為deleted运沦。并非真正刪除。
(2) 回滾指針: DB_ROLL_PTR, 回滾指針配深,指向當前記錄行的undo log信息茶袒,也就是記錄行的歷史版本
(3) 行號:DB_ROW_ID ,如果定義了主鍵,那么InnoDB會使用主鍵作為聚簇索引,如果沒有定義主鍵凉馆,那么會使用第一非空的唯一索引(NOT NULL and UNIQUE INDEX)作為聚簇索引,如果既沒有主鍵也找不到合適的非空索引薪寓,就會將DB_ROW_ID作為主鍵,自增,占6個字節(jié).
Read View 讀視圖也叫快照
(1) trx_ids 活躍事務(wù)ID列表
(2) low_limit_id 最大的事務(wù)ID+1
(3) 活躍事務(wù)列表trx_ids中最小的事務(wù)ID
Undo log日志
存儲的是老版本數(shù)據(jù)亡资,當一個事務(wù)需要讀取記錄行時,如果當前記錄行不可見向叉,可以順著undo log鏈找到滿足其可見性條件的記錄行版本锥腻。是通過回滾指針形成的鏈表結(jié)構(gòu)。
① insert undo log : 事務(wù)對insert新記錄時產(chǎn)生的undo log, 因為不存在正在對這行數(shù)據(jù)進行讀的事務(wù)母谎,所以這個日志只在事務(wù)回滾時需要, 所以在事務(wù)提交后就可以立即丟棄瘦黑。
② update undo log:: 事務(wù)對記錄進行delete和update操作時產(chǎn)生的undo log,不僅在事務(wù)回滾時需要奇唤,快照讀也需要幸斥,因為可能存在正在對這行數(shù)據(jù)進行讀的事務(wù),只有當數(shù)據(jù)庫所使用的快照中不涉及該日志記錄咬扇,對應(yīng)的回滾日志才會被purge線程刪除甲葬。
Purge線程
從前面的分析可以看出,為了實現(xiàn)InnoDB的MVCC機制懈贺,更新或者刪除操作都只是設(shè)置一下老記錄的deleted_bit经窖,并不真正將過時的記錄刪除。
為了節(jié)省磁盤空間梭灿,InnoDB有專門的purge線程來清理deleted_bit為true的記錄画侣。為了不影響MVCC的正常工作,purge線程自己也維護了一個read view(這個read view相當于系統(tǒng)中最老活躍事務(wù)的read view);如果某個記錄的deleted_bit為true堡妒,并且DB_TRX_ID相對于purge線程的read view可見配乱,那么這條記錄一定是可以被安全清除的。

Undo log的圖解


image.png

Mvcc工作的大致流程
在innodb中皮迟,創(chuàng)建一個新的事務(wù)新事務(wù)后搬泥,執(zhí)行第一個select語句的時候,innodb會創(chuàng)建一個快照(read view)万栅,快照中會保存系統(tǒng)當前不應(yīng)該被本事務(wù)看到的其他活躍事務(wù)id列表(即trx_ids)。當用戶在這個事務(wù)中要讀取某個記錄行的時候西疤,innodb會將該記錄行的DB_TRX_ID與該Read View中的一些變量進行比較烦粒,判斷是否滿足可見性條件
假設(shè)當前事務(wù)要讀取某一個記錄行,該記錄行的DB_TRX_ID(即最新修改該行的事務(wù)ID)為trx_id代赁,Read View的活躍事務(wù)列表trx_ids的上下界分別為 low_limit_id 和 up_limit_id.
具體的比較算法如下:

  1. 如果 trx_id < up_limit_id, 那么表明“最新修改該行的事務(wù)”在“當前事務(wù)”創(chuàng)建快照之前就提交了扰她,所以該記錄行的值對當前事務(wù)是可見的。直接標識為可見芭碍,返回true,
  2. 如果 trx_id >= low_limit_id, 那么表明“最新修改該行的事務(wù)”在“當前事務(wù)”創(chuàng)建快照之后才被創(chuàng)建且修改該行的徒役,所以該記錄行的值對當前事務(wù)不可見。應(yīng)該通過回滾指針找到上個記錄行版本窖壕,判斷是否可見忧勿。循環(huán)往復(fù)杉女,直到可見
  3. 如果 up_limit_id <= trx_id < low_limit_id, 那就得通過二分查找判斷trx_id 是否在trx_ids列表出現(xiàn)過,
    ① 如果出現(xiàn)過鸳吸,說明是當前read view 中某個活躍的事務(wù)提交了熏挎,那當然是不可見的,應(yīng)該通過回滾指針找到上個記錄行版本晌砾,判斷是否可見坎拐,循環(huán)往復(fù),直到可見
    ② 如果沒有出現(xiàn)過养匈,說明這個事務(wù)是已經(jīng)提交了的哼勇,標識為可見,返回true
    4.RR和RC的Read View的實現(xiàn)過程區(qū)別
    提交讀和可重復(fù)讀都是使用 MVCC 機制來實現(xiàn)的呕乎,但是實現(xiàn)過程略微有一些不同积担,
    ①在innodb中的Repeatable Read級別, 只有事務(wù)在begin之后,執(zhí)行第一條select(讀操作)時, 才會創(chuàng)建一個快照(read view)楣嘁,將當前系統(tǒng)中活躍的其他事務(wù)記錄起來磅轻;并且事務(wù)結(jié)束前都是使用的這個快照,不會重新創(chuàng)建逐虚,直到事務(wù)結(jié)束聋溜。
    ②在innodb中的Read Committed級別, 事務(wù)在begin之后,執(zhí)行每條select(讀操作)語句時叭爱,快照會被重置撮躁,即會重新創(chuàng)建一個快照(read view)。
    所以這個實現(xiàn)的差別可以達到不同的隔離級別买雾,兩個隔離級別都是快照讀


    image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末把曼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子漓穿,更是在濱河造成了極大的恐慌嗤军,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晃危,死亡現(xiàn)場離奇詭異叙赚,居然都是意外死亡,警方通過查閱死者的電腦和手機僚饭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門震叮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鳍鸵,你說我怎么就攤上這事苇瓣。” “怎么了偿乖?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵击罪,是天一觀的道長哲嘲。 經(jīng)常有香客問我,道長外邓,這世上最難降的妖魔是什么撤蚊? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮损话,結(jié)果婚禮上侦啸,老公的妹妹穿的比我還像新娘。我一直安慰自己丧枪,他們只是感情好光涂,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拧烦,像睡著了一般忘闻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恋博,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天齐佳,我揣著相機與錄音,去河邊找鬼债沮。 笑死炼吴,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的疫衩。 我是一名探鬼主播硅蹦,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闷煤!你這毒婦竟也來了童芹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤鲤拿,失蹤者是張志新(化名)和其女友劉穎假褪,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體近顷,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡生音,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了幕庐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片久锥。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡家淤,死狀恐怖异剥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情絮重,我是刑警寧澤冤寿,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布歹苦,位于F島的核電站,受9級特大地震影響督怜,放射性物質(zhì)發(fā)生泄漏殴瘦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一号杠、第九天 我趴在偏房一處隱蔽的房頂上張望蚪腋。 院中可真熱鬧,春花似錦姨蟋、人聲如沸屉凯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悠砚。三九已至,卻和暖如春堂飞,著一層夾襖步出監(jiān)牢的瞬間灌旧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工绰筛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留枢泰,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓别智,卻偏偏與公主長得像宗苍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子薄榛,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

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

  • MVCC并發(fā)控制中讳窟,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read...
    尹楷楷閱讀 1,090評論 0 5
  • 1 Mysql中的一些日志文件跟事務(wù)隔離性的介紹 1.1 redo log redo log就是保存執(zhí)行的SQL語...
    小狐憨憨閱讀 828評論 0 0
  • 1.文章適用對象: 能夠基本描述清楚mysql事務(wù)隔離級別 不可重復(fù)去或可重復(fù)讀的現(xiàn)象,想進一步探討底層設(shè)計思想的...
    華北_b5ef閱讀 1,382評論 0 1
  • MVCC(Multi-Version Concurrency Control),多版本并發(fā)控制敞恋。 MVCC是一種并...
    小丸子的呆地閱讀 749評論 1 9
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月丽啡,有人笑有人哭,有人歡樂有人憂愁硬猫,有人驚喜有人失落补箍,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,529評論 28 53