自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

數(shù)據(jù)庫 MySQL
我們再看一下對于事務(wù)原子性的定義,事務(wù)是一個不可分割的最小單位,要么全部執(zhí)行成功,要么全部失敗回滾。在這里,事務(wù)全部執(zhí)行成功依賴于 Redo Log(重做日志),而事務(wù)回滾則依賴于 Undo Log(撤銷日志)。

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

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

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

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

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

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

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

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

原子性(Atomicity)

我們再看一下對于事務(wù)原子性的定義,事務(wù)是一個不可分割的最小單位,要么全部執(zhí)行成功,要么全部失敗回滾。

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

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

圖片圖片

Redo Log

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

這里在重點說下用來控制 Redo Log 的 innodb_flush_log_at_trx_commit 參數(shù),該參數(shù)有0,1,2 三個選項:

圖片圖片

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

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

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

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

Undo Log

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

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

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

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

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

圖片圖片

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

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

持久性(Durability)

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

這種說法不能說不對,只是不太全面。

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

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

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

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

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

其具體運行機制如下圖所示:

圖片圖片

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

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

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

隔離性(Isolation)

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

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

圖片圖片

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

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

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

SELECT * FROM table1;

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

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

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

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

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

其中隱藏字段包括:

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

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

如下圖所示:

圖片圖片

一致性(Consistency)

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

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

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

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

圖片圖片


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

2021-09-27 07:11:18

MySQLACID特性

2024-10-15 10:00:06

2024-12-25 15:44:15

2022-03-30 07:28:24

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

2024-02-04 10:08:34

2021-09-17 12:50:10

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

2021-07-08 07:08:21

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

2025-02-26 12:19:52

2022-05-24 08:03:28

InnoDBMySQL數(shù)據(jù)

2010-09-08 15:55:20

SQL事務(wù)特性

2022-02-09 09:37:54

ReactorNettyI/O

2019-04-03 09:27:01

MySQLInnoDB務(wù)ACID

2015-08-13 10:29:12

面試面試官

2024-05-11 15:11:44

系統(tǒng)軟件部署

2025-04-14 11:41:12

RocketMQ長輪詢配置

2019-01-29 09:36:10

MySQLACID特性

2023-02-08 07:04:20

死鎖面試官單元

2024-09-11 22:51:19

線程通訊Object

2023-11-20 10:09:59

2024-02-20 14:10:55

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

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