最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

MySQL 是如何實(shí)現(xiàn) ACID 的?

2022-05-01 12:42 作者:劉水鏡  | 我要投稿


我們都知道,事務(wù)具有 ACID 四個(gè)特性——原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。但你知道 MySQL 是通過什么技術(shù)手段來實(shí)現(xiàn)的嗎?


ACID 簡(jiǎn)介


先來簡(jiǎn)單回顧一下 ACID 的定義:


原子性:事務(wù)作為一個(gè)整體被執(zhí)行,包含在其中的對(duì)數(shù)據(jù)庫(kù)的操作要么全部被執(zhí)行,要么都不執(zhí)行。

一致性:事務(wù)開始前和事務(wù)結(jié)束后,數(shù)據(jù)庫(kù)的完整性沒有被破壞。即寫入的數(shù)據(jù)必須完全符合所有的預(yù)設(shè)約束、觸發(fā)器、級(jí)聯(lián)回滾等。

隔離性:多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行。

持久性:已被提交的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改應(yīng)該永久保存在數(shù)據(jù)庫(kù)中。即使系統(tǒng)掛了,數(shù)據(jù)也不會(huì)丟。


我們按照:持久性 -> 原子性 -> 隔離性 -> 一致性 的順序來討論。

PS:本文基于 InnoDB


持久性


我們知道程序修改數(shù)據(jù)的時(shí)候,是先將數(shù)據(jù)從磁盤加載到內(nèi)存,然后修改完再由內(nèi)存寫回磁盤。持久化其實(shí)就是將內(nèi)存里的數(shù)據(jù)寫入磁盤。因此,持久性的關(guān)鍵就在于如何保證數(shù)據(jù)可以由內(nèi)存順利寫入磁盤。

我們有以下幾個(gè)方案:


方案一:

  1. 加載數(shù)據(jù)到內(nèi)存

  2. 修改內(nèi)存

  3. 然后寫回磁盤

  4. 提交事務(wù)


方案二:

  1. 加載數(shù)據(jù)到內(nèi)存

  2. 修改內(nèi)存

  3. 提交事務(wù)

  4. 后臺(tái)寫回磁盤


第一種方案,靠譜是靠譜,但頻繁 I/O 性能太低,會(huì)嚴(yán)重拖累 MySQL 的吞吐量。

第二種方案雖然性能上來了,但如果在第四步時(shí)宕機(jī)了,而系統(tǒng)認(rèn)為事務(wù)已提交,這時(shí)候就會(huì)丟失數(shù)據(jù)了。


那怎么辦呢?MySQL 給出的方案是 WAL(Write Ahead Log)機(jī)制。WAL 翻譯過來就是先寫日志的意思。這個(gè)日志就是 redo log。具體做法是:

  1. 加載數(shù)據(jù)到內(nèi)存

  2. 修改內(nèi)存

  3. 寫入 redo log

  4. 提交事務(wù)

  5. 后臺(tái)寫回磁盤


如果第五步時(shí)系統(tǒng)宕機(jī),也可以通過 redo log 來恢復(fù)。


你可能有疑問:寫入 redo log 不也有磁盤 I/O 嗎?這不是脫了那啥再那啥,多此一舉嗎?寫 redo log 和寫表的區(qū)別就在于隨機(jī)寫和順序?qū)?。MySQL 的表數(shù)據(jù)是隨機(jī)存儲(chǔ)在磁盤中的,而 redo log 是一塊固定大小的連續(xù)空間。而磁盤順序?qū)懭胍入S機(jī)寫入快幾個(gè)數(shù)量級(jí)。

因此,這種方案即保證了數(shù)據(jù)的安全,性能上也能夠接受。


原子性


假如一個(gè)事務(wù)做了如下操作:

  1. 插入一條數(shù)據(jù) insert into user values('1','小劉','18')

  2. 更新一條數(shù)據(jù) update user set name = '小水' where id = 2

  3. 刪除一條數(shù)據(jù) delete from user where id = 3


根據(jù)原子性的規(guī)定,這三個(gè)操作要么都成功,要么都失敗。那么問題就來了,如何保證 3 失敗的情況下,讓 1,2 也回退呢?


答案就是 undo log。


每個(gè)事務(wù)操作(增刪改)都會(huì)記錄一條與之對(duì)應(yīng)的 undo log:

  1. insert 記錄插入的主鍵,回滾則根據(jù)該主鍵刪除記錄

  2. update 記錄記錄主鍵和被修改列的當(dāng)前值,回滾則根據(jù)主鍵和之前的值覆蓋

  3. delete 為記錄添加刪除標(biāo)志,即 MySQL 內(nèi)部的邏輯刪除,回滾根據(jù)主鍵恢復(fù)


隔離性


數(shù)據(jù)庫(kù)事務(wù)有四種隔離級(jí)別,不同的級(jí)別可能會(huì)出現(xiàn)各種各樣的問題(臟讀、幻讀、不可重復(fù)讀),關(guān)系如下:

MySQL 中 RR 級(jí)別已經(jīng)解決了幻讀問題。


并發(fā)的情況才需要隔離,而并發(fā)有三種組合:

  1. 讀讀

  2. 讀寫

  3. 寫寫


「讀讀」的情況,不需要隔離;「讀寫」通過 MVCC 隔離;「寫寫」只能通過鎖來隔離。


MVCC(Multi Version Concurrency Control,多版本并發(fā)控制)作用于 RC 和 RR 級(jí)別??梢詾槭聞?wù)中的讀操作創(chuàng)建一個(gè)快照(Readview),從而來避免被其他事務(wù)干擾。

RC 級(jí)別下,一個(gè)事務(wù)中的每次(同參數(shù))讀都會(huì)創(chuàng)建一個(gè) Readview。

RR 級(jí)別下,一個(gè)事務(wù)中只在第一次讀時(shí)創(chuàng)建 Readview,后面再次讀,仍然讀取該 Readview。


「寫寫」的情況通過三種鎖來實(shí)現(xiàn)隔離:Record Lock、Gap Lock 和 Next Key Lock(前兩者的組合)。


Record Lock 鎖住一條數(shù)據(jù),從而使其他事務(wù)無法修改和刪除;Gap Lock 鎖住一個(gè)范圍,從而使其他事務(wù)不能在該區(qū)間插入數(shù)據(jù);Next Key Lock 鎖住具體數(shù)據(jù)和區(qū)間,從而使其他事務(wù)無法更新、刪除和在該區(qū)間插入數(shù)據(jù)。

MVCC + 鎖 使得 MySQL 在 RR 級(jí)別避免了幻讀問題。


一致性


很多人聊到一致性,很喜歡拿轉(zhuǎn)賬的業(yè)務(wù)舉例,但這明顯是原子性的范疇——A 賬戶扣錢,B 賬戶加錢,兩個(gè) Update 操作,要么都成功,要么都失敗。

一致性更側(cè)重是,數(shù)據(jù)的完整性:主外鍵約束、唯一索引、列完整等。MySQL 中保證一致性主要靠 CR(Crash Recovery)和 DWB(Doublewrite Buffer)來保證的。

這兩個(gè)特性比較復(fù)雜,一篇文章根本講不完,如果你感興趣可以去看官方文檔,或者留言告訴我,我來安排。


最后


一致性是一個(gè)比較特殊的存在,它和原子性、隔離性有一層「你中有我,我中有你」的曖昧關(guān)系。比如轉(zhuǎn)賬的業(yè)務(wù)場(chǎng)景,如果說它屬于一致性的范疇,也能夠說得通,可以叫「用戶自定義一致性」;另外,隔離性使得事務(wù)之間互不影響的最終效果也是保證了數(shù)據(jù)的一致。


MySQL 是如何實(shí)現(xiàn) ACID 的?的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
牟定县| 黎川县| 阿鲁科尔沁旗| 噶尔县| 法库县| 漳浦县| 安龙县| 伊宁市| 景德镇市| 弥渡县| 崇仁县| 定襄县| 柏乡县| 策勒县| 永靖县| 新泰市| 抚州市| 舒城县| 衢州市| 扎鲁特旗| 三河市| 华容县| 阳朔县| 岳阳县| 务川| 武穴市| 贵定县| 永年县| 江孜县| 电白县| 清水河县| 泗水县| 新乡市| 浪卡子县| 永平县| 沅陵县| 墨竹工卡县| 秦皇岛市| 竹山县| 莎车县| 贵德县|