偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試官:MySQL InnoDB事務(wù)中的ACID特性是如何實(shí)現(xiàn)的?

數(shù)據(jù)庫(kù) MySQL
我們?cè)倏匆幌聦?duì)于事務(wù)原子性的定義,事務(wù)是一個(gè)不可分割的最小單位,要么全部執(zhí)行成功,要么全部失敗回滾。在這里,事務(wù)全部執(zhí)行成功依賴(lài)于 Redo Log(重做日志),而事務(wù)回滾則依賴(lài)于 Undo Log(撤銷(xiāo)日志)。

不得不說(shuō),現(xiàn)在的面試還是比幾年前卷了很多的。

以前的面試官大概率只會(huì)問(wèn),“說(shuō)下 MySQL InnoDB 事務(wù)中的 ACID 特性各是什么”僅此而已了,根本不會(huì)涉及到什么底層實(shí)現(xiàn)。

嗯,那就卷起來(lái)吧,接下來(lái)我們先看看 ACID 特性的定義,然后再延展開(kāi)來(lái)往底層實(shí)現(xiàn)上講。

原子性(Atomicity),事務(wù)是一個(gè)不可分割的最小單位,要么全部執(zhí)行成功,要么全部失敗回滾。

一致性(Consistency),業(yè)務(wù)邏輯的一致性,保證事務(wù)從一個(gè)一致的業(yè)務(wù)狀態(tài)轉(zhuǎn)換到另一個(gè)。

比如轉(zhuǎn)賬功能,從你的賬戶(hù)里扣減10元,必須在我的賬戶(hù)里增加10元。

隔離性(Isolation),多個(gè)并發(fā)執(zhí)行的事務(wù)是相互隔離、互不干擾的。當(dāng)然,隔離是分等級(jí)的,這就是所謂的事務(wù)隔離級(jí)別。

持久性(Durability),事務(wù)提交后就會(huì)在硬盤(pán)中持久化,數(shù)據(jù)不會(huì)丟失。

原子性(Atomicity)

我們?cè)倏匆幌聦?duì)于事務(wù)原子性的定義,事務(wù)是一個(gè)不可分割的最小單位,要么全部執(zhí)行成功,要么全部失敗回滾。

在這里,事務(wù)全部執(zhí)行成功依賴(lài)于 Redo Log(重做日志),而事務(wù)回滾則依賴(lài)于 Undo Log(撤銷(xiāo)日志)。

也就是說(shuō),事務(wù)的原子性是通過(guò) Redo Log(重做日志)和Undo Log(撤銷(xiāo)日志)實(shí)現(xiàn)的。

圖片圖片

Redo Log

當(dāng)事務(wù)被提交的時(shí)候,對(duì)數(shù)據(jù)表的寫(xiě)操作并不是直接刷新磁盤(pán)上的數(shù)據(jù)文件上,而是先被寫(xiě)入到 Redo Log 中(默認(rèn)情況下),再通過(guò) Master Thread 適時(shí)刷新到磁盤(pán)上的數(shù)據(jù)文件中,其目的是為了減少磁盤(pán)頻繁的隨機(jī) IO 操作。

這里在重點(diǎn)說(shuō)下用來(lái)控制 Redo Log 的 innodb_flush_log_at_trx_commit 參數(shù),該參數(shù)有0,1,2 三個(gè)選項(xiàng):

圖片圖片

參數(shù)為0:事務(wù)提交時(shí)并不需要將 Redo Log 寫(xiě)入到磁盤(pán)中,僅僅寫(xiě)入到Log Buffer 中,然后通過(guò) Master Thread 每秒鐘進(jìn)行一次 Redo Log 的刷盤(pán)操作。

等于1:默認(rèn)值,在事務(wù)進(jìn)行中不斷地寫(xiě)入到 Redo Log Buffer 中,在事務(wù)提交時(shí)必須將事務(wù)的 Redo Log 刷新到磁盤(pán)上。

等于2:事務(wù)提交時(shí)將僅將 Redo Log 寫(xiě)入到 OS Buffer 中,然后操作系統(tǒng)每秒鐘進(jìn)行一次 Redo Log 的刷盤(pán)操作。

選擇該選項(xiàng),如果只是 MySQL 數(shù)據(jù)庫(kù)掛掉了,操作系統(tǒng)沒(méi)有問(wèn)題的情況下,對(duì)應(yīng)的事務(wù)數(shù)據(jù)并沒(méi)有丟失。

Undo Log

在事務(wù)提交前,MySQL InnoDB 會(huì)先將用于回滾操作的 SQL 語(yǔ)句保存到 Undo Log 中,以便于將其恢復(fù)到事務(wù)開(kāi)始前的狀態(tài),其屬于邏輯日志。

舉例說(shuō)明:如果 MySQL InnoDB 進(jìn)行 insert 操作時(shí),其對(duì)應(yīng)的 Undo Log 為 delete 語(yǔ)句,反之則是 delete 操作對(duì)應(yīng) Undo Log 的 insert 語(yǔ)句。

如果 MySQL InnoDB 進(jìn)行 update 操作時(shí),其對(duì)應(yīng)的 Undo Log 為反向 update 語(yǔ)句。

Undo Log 是通過(guò)回滾段和 Undo 段來(lái)進(jìn)行存儲(chǔ)的,其中一個(gè)事務(wù)系統(tǒng)段可保存 256 個(gè)回滾段,一個(gè)回滾段可保存 1024 個(gè) Undo 段的信息。

三者關(guān)系如下:

圖片圖片

BTW:該圖截取自《MySQL 內(nèi)核:InnoDB存儲(chǔ)引擎》

Undo Log 除了保證原子性,還可以通過(guò)其實(shí)現(xiàn) MVCC(多版本并發(fā)控制)機(jī)制,支持 MySQL InnoDB 的快照讀的操作。

持久性(Durability)

網(wǎng)上的很多資料說(shuō),MySQL InnoDB 的持久性是通過(guò)具備 WAL (Write-Ahead Logging)機(jī)制的 Redo Log 來(lái)實(shí)現(xiàn)的,要求所有數(shù)據(jù)庫(kù)寫(xiě)操作在寫(xiě)入數(shù)據(jù)文件之前,必須先寫(xiě)入到日志文件中。

這種說(shuō)法不能說(shuō)不對(duì),只是不太全面。

除了 Redo Log 之外,Double Write 機(jī)制也是 MySQL InnoDB用來(lái)保證數(shù)據(jù)頁(yè)完整性的技術(shù),從而保證了持久性,接下來(lái)我們了解一下它的作用。

眾所周知,MySQL InnoDB 的最小 IO 單元為默認(rèn) 16KB 的 Page,無(wú)論其存儲(chǔ)在 Buffer Pool 中還是在磁盤(pán)上,而 Linux 的文件系統(tǒng) Page 只有 4KB。

這也就意味著,如果 MySQL InnoDB 將一個(gè) Page 的數(shù)據(jù)進(jìn)行刷盤(pán)操作,需要寫(xiě)四個(gè)文件系統(tǒng)的 Page,但這個(gè)操作并不是原子性的。

如果在這個(gè)過(guò)程中遇到系統(tǒng)崩潰或者服務(wù)器宕機(jī),就會(huì)導(dǎo)致四個(gè)文件系統(tǒng)的 Page 沒(méi)有全部寫(xiě)完,從而出現(xiàn) MySQL InnoDB 的 Page 損壞的情況,而 Double Write 機(jī)制則正是為了解決這個(gè)問(wèn)題。

Double Write 機(jī)制包含兩個(gè)部分,內(nèi)存中的 Double Write Buffer 和磁盤(pán)共享表空間的 128 個(gè)數(shù)據(jù)頁(yè),大小都是 2MB。

其具體運(yùn)行機(jī)制如下圖所示:

圖片圖片

在事務(wù)提交時(shí) Redo Log 被刷新到磁盤(pán)上,隨后 Master Thread 適時(shí)將 Buffer Pool 中的臟頁(yè)刷新到 Double Write Buffer 中,最后將 Double Write Buffer 中的數(shù)據(jù)寫(xiě)入到 Double Write 共享表空間和數(shù)據(jù)文件中。

如果在寫(xiě)入 Double Write 共享表空間的時(shí)候出現(xiàn)宕機(jī)崩潰的情況,此時(shí)數(shù)據(jù)文件仍然是完整的,可以通過(guò) Redo Log 進(jìn)行恢復(fù)。

反之,如果在寫(xiě)入 Double Write 共享表空間的時(shí)候成功了,卻在寫(xiě)入數(shù)據(jù)文件的時(shí)候出現(xiàn)宕機(jī)崩潰的情況,則如上圖所示:可先通過(guò) Double Write 共享表空間的 Page 對(duì)數(shù)據(jù)文件中的 Page 進(jìn)行覆蓋,再通過(guò) Redo Log 進(jìn)行恢復(fù)。

隔離性(Isolation)

MySQL InnoDB 的默認(rèn)事務(wù)隔離級(jí)別是可重復(fù)讀,其隔離性是通過(guò)鎖機(jī)制和 MVCC(多版本并發(fā)控制)來(lái)實(shí)現(xiàn)的。

先說(shuō)說(shuō)寫(xiě)操作,如下圖所示,MySQL InnoDB 有很多類(lèi)型的鎖,這些鎖機(jī)制可以避免多個(gè)事務(wù)對(duì)同一項(xiàng)數(shù)據(jù)資源進(jìn)行修改,從而保證了各事務(wù)間相互隔離、互不干擾。

圖片圖片

這里所說(shuō)的“同一項(xiàng)數(shù)據(jù)資源”不僅僅是指一行數(shù)據(jù),也可以是數(shù)據(jù)頁(yè)級(jí)別、表級(jí)別甚至是庫(kù)級(jí)別。

MySQL InnoDB 中的讀操作分為快照讀和當(dāng)前讀兩種。

快照讀是指在事務(wù)開(kāi)始時(shí)將數(shù)據(jù)的一個(gè)副本保存起來(lái),然后在整個(gè)事務(wù)過(guò)程中使用這個(gè)副本進(jìn)行讀取,不受其他并發(fā)事務(wù)的影響,SQL語(yǔ)句如下:

SELECT * FROM table1;

當(dāng)前讀是指在事務(wù)期間每次讀取數(shù)據(jù)都返回最新的數(shù)據(jù),不使用事務(wù)開(kāi)始時(shí)的數(shù)據(jù)副本,SQL語(yǔ)句如下:

SELECT * FROM table1 FOR UPDATE;
SELECT * FROM table1 LOCK IN SHARE MODE;

當(dāng)前讀的隔離性仍然是通過(guò)鎖機(jī)制來(lái)實(shí)現(xiàn)的,而快照讀則是MVCC(多版本并發(fā)控制)。

MVCC 是一種數(shù)據(jù)庫(kù)中用于處理并發(fā)讀寫(xiě)事務(wù)的技術(shù),通過(guò)維護(hù)數(shù)據(jù)的不同版本的方式,來(lái)實(shí)現(xiàn)查詢(xún)操作在不需要等待其他事務(wù)持有的鎖的情況下進(jìn)行,從而提高了數(shù)據(jù)庫(kù)的并發(fā)性。

MVCC 是通過(guò)數(shù)據(jù)行的隱藏字段、Undo Log 和 Read View 來(lái)實(shí)現(xiàn)的。

其中隱藏字段包括:

  • DB_TRX_ID:6 Byte,最近一次插入或修改該行記錄的事務(wù)ID。
  • DB_ROLL_PTR:7 Byte,回滾指針,指向存儲(chǔ)在Undo Log中的這條記錄的上一個(gè)版本。
  • DB_ROW_ID:6 Byte,隱藏的自增主鍵,如果數(shù)據(jù)表中沒(méi)有設(shè)定主鍵的話(huà),MySQL InnoDB 會(huì)自動(dòng)通過(guò) DB_ROW_ID 產(chǎn)生一個(gè)聚簇索引。

再來(lái)說(shuō)說(shuō) Read View,當(dāng)我們發(fā)起快照讀的時(shí)候,會(huì)對(duì)該行記錄生成一個(gè) Read View(讀視圖),用來(lái)判斷當(dāng)前事務(wù)能夠看到哪個(gè)版本的數(shù)據(jù),既可能是當(dāng)前數(shù)據(jù)表中最新的數(shù)據(jù),也可能是該行記錄在 Undo Log 里面的某個(gè)版本的數(shù)據(jù)。

如下圖所示:

圖片圖片

一致性(Consistency)

有的同學(xué)在一致性保證這塊提到了 Binlog,我認(rèn)為不太準(zhǔn)確,因?yàn)檫@里說(shuō)的是實(shí)現(xiàn)事務(wù)的一致性,而不是主從庫(kù)的數(shù)據(jù)一致性,不一樣的。

事務(wù)的一致性特性,是為了保障業(yè)務(wù)邏輯的一致性,保證事務(wù)從一個(gè)一致的業(yè)務(wù)狀態(tài)轉(zhuǎn)換到另一個(gè)。

我認(rèn)為事務(wù)的 ACID 之間,并不是像《金字塔原理》一書(shū)中提到的 MECE 原則一樣 —— 相互獨(dú)立,完全窮盡。

事務(wù)的原子性、持久性和隔離性都是為了實(shí)現(xiàn)事務(wù)的一致性,讓業(yè)務(wù)狀態(tài)可以正常流轉(zhuǎn)。

圖片圖片


責(zé)任編輯:武曉燕 來(lái)源: 托尼學(xué)長(zhǎng)
相關(guān)推薦

2021-09-27 07:11:18

MySQLACID特性

2024-10-15 10:00:06

2025-10-28 02:00:00

2024-02-04 10:08:34

2024-12-25 15:44:15

2022-03-30 07:28:24

MySQL數(shù)據(jù)庫(kù)ACID

2021-09-17 12:50:10

MySQL數(shù)據(jù)庫(kù)ACID

2021-07-08 07:08:21

MySQL ACID 數(shù)據(jù)庫(kù)

2025-02-26 12:19:52

2025-09-03 04:00:00

小紅書(shū)Feed流系統(tǒng)

2025-10-21 08:06:20

2022-05-24 08:03:28

InnoDBMySQL數(shù)據(jù)

2022-02-09 09:37:54

ReactorNettyI/O

2010-09-08 15:55:20

SQL事務(wù)特性

2015-08-13 10:29:12

面試面試官

2024-05-11 15:11:44

系統(tǒng)軟件部署

2025-04-14 11:41:12

RocketMQ長(zhǎng)輪詢(xún)配置

2019-04-03 09:27:01

MySQLInnoDB務(wù)ACID

2019-01-29 09:36:10

MySQLACID特性

2024-02-20 14:10:55

系統(tǒng)緩存冗余
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)