目錄
Redo 的作用
Redo 的組成
什麼時候寫Redo?
Redo的整體流程
redo如何保證交易的持久性?
Redo在InnoDB中是如何實現的?與mini-transaction的聯繫?
首頁 資料庫 mysql教程 MySQL事務中的redo與undo的分析(圖文)

MySQL事務中的redo與undo的分析(圖文)

Jan 15, 2019 am 10:51 AM
mysql

這篇文章帶給大家的內容是關於MySQL事務中的redo與undo的分析(圖文),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

我們都知道事務有4種特性:原子性、一致性、隔離性和持久性,在事務中的操作,要麼全部執行,要麼全部不做,這就是事務的目的。事務的隔離性由鎖定機制實現,原子性、一致性和持久性由事務的redo 日誌和undo 日誌來保證。所以這篇文章將討論關於事務中的redo和undo的幾個問題:

  • redo 日誌與undo日誌分別是什麼?

  • redo 如何保證交易的持久性?

  • undo log 是否是redo log的逆過程?

redo log

#Redo 的型別

重做日誌(redo log)用來保證事務的持久性,即事務ACID中的D。實際上它可以分成以下兩種類型:

  • 物理Redo日誌

  • #邏輯Redo日誌

在InnoDB儲存引擎中,大部分情況下Redo是實體日誌,記錄的是資料頁的物理變化。而邏輯Redo日誌,不是記錄頁面的實際修改,而是記錄修改頁面的一類操作,例如新建資料頁時,需要記錄邏輯日誌。關於邏輯Redo日誌涉及更底層的內容,這裡我們只需要記住絕大數情況下,Redo是實體日誌即可,DML對頁的修改操作,均需要記錄Redo.

Redo 的作用

Redo log的主要作用是用於資料庫的崩潰復原

Redo 的組成

Redo log可以簡單分成以下兩個部分:

  • 一是記憶體中重做日誌緩衝(redo log buffer),是易失的,在記憶體中

  • 二是重做日誌檔(redo log file ),是持久的,保存在磁碟中

什麼時候寫Redo?

上面那張圖簡單地體現了Redo的寫入流程,這裡再細說下寫入Redo的時機:

  • 在資料頁修改完成之後,在髒頁刷出磁碟之前,寫入redo日誌。注意的是先修改數據,後寫日誌

  • redo日誌比數據頁先寫回磁碟

  • 聚集索引、二級索引、undo頁面的修改,均需記錄Redo日誌。

Redo的整體流程

下面以更新交易為例,在宏觀上掌握redo log 流轉過程,如下圖所示:

MySQL事務中的redo與undo的分析(圖文)

  • 第一步:先將原始資料從磁碟中讀入記憶體中來,修改資料的記憶體拷貝

  • #第二步:產生一條重做日誌並寫入redo log buffer,記錄的是資料被修改後的值

  • 第三步:當交易commit時,將redo log buffer中的內容刷新到redo log file,對redo log file採用追加寫的方式

  • 第四步:定期將記憶體中修改的資料刷新到磁碟中

redo如何保證交易的持久性?

InnoDB是交易的儲存引擎,其透過Force Log at Commit 機制實現交易的持久性,即當交易提交時,先將redo log buffer 寫入到redo log file 進行持久化,待交易的commit作業完成時才算完成。這種做法也稱為 Write-Ahead Log(預先日誌持久化),在持久化一個資料頁之前,先將記憶體中對應的日誌頁持久化。

為了確保每次日誌都寫入redo log file,在每次將redo buffer寫入redo log file之後,預設情況下,InnoDB儲存引擎都需要呼叫一次fsync操作 ,因為重做日誌開啟並沒有O_DIRECT選項,所以重做日誌先寫入到檔案系統快取。為了確保重做日誌寫入到磁碟,必須進行一次 fsync操作。 fsync是一種系統呼叫操作,其fsync的效率取決於磁碟的效能,因此磁碟的效能也影響了交易提交的效能,也就是資料庫的效能。
(O_DIRECT選項是在Linux系統中的選項,使用該選項後,對檔案進行直接IO操作,不經過檔案系統緩存,直接寫入磁碟)

##上面提到的

Force Log at Commit機制就是靠InnoDB儲存引擎提供的參數innodb_flush_log_at_trx_commit來控制的,該參數可以控制redo log刷新到磁碟的策略,設定該參數值也可以允許使用者設定非持久性的情況發生,具體如下:

  • 當設定參數為1時,(預設為1),表示交易提交時必須呼叫一次

    fsync 操作,最安全的配置,保障持久性

  • 當設定參數為2時,則在交易提交時只做write 操作,只保證將redo log buffer寫到系統的頁面快取中,不進行fsync操作,因此如果MySQL資料庫宕機時不會遺失事務,但作業系統宕機則可能遺失事務

  • 當設定參數為0時,表示交易提交時不進行寫入redo log操作,這個操作僅在master thread 完成,而在master thread每1秒進行一次重做日誌的fsync操作,因此實例crash 最多遺失1秒鐘內的交易。 (master thread是負責將緩衝池中的資料非同步刷新到磁碟,保證資料的一致性)

#fsyncwrite操作其實是系統呼叫函數,在許多持久化場景都有使用到,例如Redis 的AOF持久化中也使用到兩個函數。 fsync操作將資料提交到硬碟中,強制硬碟同步,將一直阻塞到寫入硬碟完成後返回,大量進行fsync操作就有效能瓶頸,而write 操作將資料寫到系統的頁面快取後立即返回,後面依靠系統的調度機制將快取資料刷到磁碟中去,其順序是user buffer——> page cache——>disk。

MySQL事務中的redo與undo的分析(圖文)

除了上面談到的Force Log at Commit機制保證交易的持久性,實際上重做日誌的實作還要依賴於mini-transaction。

Redo在InnoDB中是如何實現的?與mini-transaction的聯繫?

Redo的實作實際上跟mini-transaction緊密相關,mini-transaction是一種InnoDB內部使用的機制,透過mini-transaction來保證並發事務操作下以及資料庫異常時資料頁中數據的一致性,但它不屬於事務。

為了使得mini-transaction保證資料頁資料的一致性,mini-transaction必須遵循以下三種協定

  • The FIX Rules

  • Write-Ahead Log

  • #Force-log-at-commit

## The FIX Rules

修改一個資料頁時需要取得該頁的x-latch(排他鎖),取得一個資料頁時需要該頁的s-latch(讀鎖定或稱為共用鎖) 或是x-latch,持有該頁的鎖直到修改或存取該頁的操作完成。

Write-Ahead Log

在前面闡述中就提到了Write-Ahead Log(預先寫日誌)。在持久化一個資料頁之前,必須先將記憶體中對應的日誌頁持久化。每個頁都有一個LSN(log sequence number),代表日誌序號,(LSN佔用8字節,單調遞增), 當一個資料頁需要寫入到持久化設備之前,要求記憶體中小於該頁LSN的日誌先寫入持久化設備

那為什麼必須先寫日誌呢?可不可以不寫日誌,直接將資料寫入磁碟?原則上是可以的,只不過會產生一些問題,資料修改會產生隨機IO,但日誌是順序IO,append方式順序寫,是一種串列的方式,這樣才能充分利用磁碟的效能。

Force-log-at-commit

這一點也就是前文提到的如何保證事務的持久性的內容,這裡再次總結一下,與上面的內容相呼應。在一個交易中可以修改多個頁,Write-Ahead Log 可以保證單一資料頁的一致性,但無法保證交易的持久性,Force-log-at-commit 要求當一個交易提交時,其產生所有的mini -transaction 日誌必須刷新到磁碟中,若日誌刷新完成後,在緩衝池中的頁刷新到持久化儲存裝置前資料庫發生了宕機,那麼資料庫重新啟動時,可以透過日誌來保證資料的完整性。

重做日誌的寫入流程

MySQL事務中的redo與undo的分析(圖文)

#上圖表示了重做日誌的寫入流程,每個mini-transaction對應每一條DML操作,例如一條update語句,其由mini-transaction來保證,對資料修改後,產生redo1,首先將其寫入mini-transaction私有的Buffer中,update語句結束後,將redo1從私有Buffer拷貝到公有的Log Buffer。當整個外部交易提交時,將redo log buffer再刷入到redo log file中。

undo log

undo log的定義

undo log主要記錄的是資料的邏輯變化,為了在發生錯誤時回滾之前的操作,需要將先前的操作都記錄下來,然後在發生錯誤時才可以回滾。

undo log的作用

undo是一種邏輯日誌,有兩個作用:

  • 用於交易的回滾

  • MVCC

關於MVCC(多版本並發控制)的內容這裡就不多說了,本文將重點放在undo log用於交易的回溯。

undo日誌,只將資料庫邏輯地恢復到原來的樣子,在回滾的時候,它實際上是做的相反的工作,比如一條INSERT ,對應一條DELETE,對於每個UPDATE,對應一條相反的UPDATE,將修改前的行放回去。 undo日誌用於交易的回滾操作進而保障了交易的原子性。

undo log的寫入時機

  • DML作業修改叢集索引前,記錄undo日誌

  • 二級索引記錄的修改,不記錄undo日誌

要注意的是,undo頁面的修改,同樣需要記錄redo日誌。

undo的儲存位置

在InnoDB儲存引擎中,undo儲存在回滾區段(Rollback 在Segment)中,每個回滾段記錄了1024個undo log segment,而在每個undo log segment段中進行undo 頁的申請,在5.6以前,Rollback Segment是在共享表空間裡的,5.6.3之後,可透過 innodb_undo_tablespace設定undo儲存的位置。

undo的類型

##在InnoDB儲存引擎中,undo log分為:

  • insert undo log

  • update undo log

insert undo log是指在insert 操作中產生的undo log,因為insert操作的記錄,只對事務本身可見,對其他事務不可見。故該undo log可以在交易提交後直接刪除,不需要進行purge操作。

而update undo log記錄的是對delete 和update操作產生的undo log,該undo log可能需要提供MVCC機制,因此不能再交易提交時就進行刪除。提交時放入undo log鍊錶,等待purge執行緒進行最後的刪除。

補充:purge執行緒兩個主要作用是:清理undo頁和清除page裡面有Delete_Bit標識的資料行。在InnoDB中,交易中的Delete操作其實不是真正的刪除資料行,而是一種Delete Mark操作,在記錄上標識Delete_Bit,而不刪除記錄。是一種"假刪除",只是做了個標記,真正的刪除工作需要後台purge線程去完成。

undo log 是否是redo log的逆過程?

undo log 是否是redo log的逆過程?其實從前文就可以得出答案了,undo log是邏輯日誌,對事務回滾時,只是將資料庫邏輯地恢復到原來的樣子,而redo log是實體日誌,記錄的是資料頁的實體變化,顯然undo log不是redo log的逆過程。

redo & undo總結

以下是redo log undo log的簡化過程,以便於理解兩種日誌的過程:

假设有A、B两个数据,值分别为1,2.
1. 事务开始
2. 记录A=1到undo log
3. 修改A=3
4. 记录A=3到 redo log
5. 记录B=2到 undo log
6. 修改B=4
7. 记录B=4到redo log
8. 将redo log写入磁盘
9. 事务提交
登入後複製
實際上,在insert/update/delete操作中,redo和undo分別記錄的內容都不一樣,量也不一樣。在InnoDB記憶體中,一般的順序如下:

  • 寫undo的redo

  • 寫undo

  • ##修改資料頁
  • 寫Redo
#小結

本文分析了事務中的redo和undo日誌,參考了一些資料書整理得出,可能有些地方表述的不清楚。如有不對之處,歡迎指出。

#

以上是MySQL事務中的redo與undo的分析(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

MySQL:世界上最受歡迎的數據庫的簡介 MySQL:世界上最受歡迎的數據庫的簡介 Apr 12, 2025 am 12:18 AM

MySQL是一種開源的關係型數據庫管理系統,主要用於快速、可靠地存儲和檢索數據。其工作原理包括客戶端請求、查詢解析、執行查詢和返回結果。使用示例包括創建表、插入和查詢數據,以及高級功能如JOIN操作。常見錯誤涉及SQL語法、數據類型和權限問題,優化建議包括使用索引、優化查詢和分錶分區。

MySQL的位置:數據庫和編程 MySQL的位置:數據庫和編程 Apr 13, 2025 am 12:18 AM

MySQL在數據庫和編程中的地位非常重要,它是一個開源的關係型數據庫管理系統,廣泛應用於各種應用場景。 1)MySQL提供高效的數據存儲、組織和檢索功能,支持Web、移動和企業級系統。 2)它使用客戶端-服務器架構,支持多種存儲引擎和索引優化。 3)基本用法包括創建表和插入數據,高級用法涉及多表JOIN和復雜查詢。 4)常見問題如SQL語法錯誤和性能問題可以通過EXPLAIN命令和慢查詢日誌調試。 5)性能優化方法包括合理使用索引、優化查詢和使用緩存,最佳實踐包括使用事務和PreparedStatemen

為什麼要使用mysql?利益和優勢 為什麼要使用mysql?利益和優勢 Apr 12, 2025 am 12:17 AM

選擇MySQL的原因是其性能、可靠性、易用性和社區支持。 1.MySQL提供高效的數據存儲和檢索功能,支持多種數據類型和高級查詢操作。 2.採用客戶端-服務器架構和多種存儲引擎,支持事務和查詢優化。 3.易於使用,支持多種操作系統和編程語言。 4.擁有強大的社區支持,提供豐富的資源和解決方案。

apache怎麼連接數據庫 apache怎麼連接數據庫 Apr 13, 2025 pm 01:03 PM

Apache 連接數據庫需要以下步驟:安裝數據庫驅動程序。配置 web.xml 文件以創建連接池。創建 JDBC 數據源,指定連接設置。從 Java 代碼中使用 JDBC API 訪問數據庫,包括獲取連接、創建語句、綁定參數、執行查詢或更新以及處理結果。

docker怎麼啟動mysql docker怎麼啟動mysql Apr 15, 2025 pm 12:09 PM

在 Docker 中啟動 MySQL 的過程包含以下步驟:拉取 MySQL 鏡像創建並啟動容器,設置根用戶密碼並映射端口驗證連接創建數據庫和用戶授予對數據庫的所有權限

MySQL的角色:Web應用程序中的數據庫 MySQL的角色:Web應用程序中的數據庫 Apr 17, 2025 am 12:23 AM

MySQL在Web應用中的主要作用是存儲和管理數據。 1.MySQL高效處理用戶信息、產品目錄和交易記錄等數據。 2.通過SQL查詢,開發者能從數據庫提取信息生成動態內容。 3.MySQL基於客戶端-服務器模型工作,確保查詢速度可接受。

laravel入門實例 laravel入門實例 Apr 18, 2025 pm 12:45 PM

Laravel 是一款 PHP 框架,用於輕鬆構建 Web 應用程序。它提供一系列強大的功能,包括:安裝: 使用 Composer 全局安裝 Laravel CLI,並在項目目錄中創建應用程序。路由: 在 routes/web.php 中定義 URL 和處理函數之間的關係。視圖: 在 resources/views 中創建視圖以呈現應用程序的界面。數據庫集成: 提供與 MySQL 等數據庫的開箱即用集成,並使用遷移來創建和修改表。模型和控制器: 模型表示數據庫實體,控制器處理 HTTP 請求。

centos7如何安裝mysql centos7如何安裝mysql Apr 14, 2025 pm 08:30 PM

優雅安裝 MySQL 的關鍵在於添加 MySQL 官方倉庫。具體步驟如下:下載 MySQL 官方 GPG 密鑰,防止釣魚攻擊。添加 MySQL 倉庫文件:rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm更新 yum 倉庫緩存:yum update安裝 MySQL:yum install mysql-server啟動 MySQL 服務:systemctl start mysqld設置開機自啟動

See all articles