圖文結合帶你搞定MySQL日誌之Undo log(回滾日誌)

来源:https://www.cnblogs.com/greatsql/archive/2022/10/12/16785010.html
-Advertisement-
Play Games

GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 文章導讀: 什麼是Undo Log? Undo:意為撤銷或取消,以撤銷操作為目的,返回某個狀態的操作。 Undo Log:資料庫事務開始之前,會將要修改 ...


  • GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
  • GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。

文章導讀:

1

什麼是Undo Log?

Undo:意為撤銷或取消,以撤銷操作為目的,返回某個狀態的操作。

Undo Log:資料庫事務開始之前,會將要修改的記錄放到Undo日誌里,當事務回滾時或者資料庫崩潰時,可以利用UndoLog撤銷未提交事務對資料庫產生的影響。

Undo Log是事務原子性的保證。在事務中更新數據的前置操作其實是要先寫入一個Undo Log

如何理解Undo Log

事務需要保證原子性,也就是事務中的操作要麼全部完成,要麼什麼也不做。但有時候事務執行到一半會出現一些情況,比如:

  • 情況一:事務執行過程中可能遇到各種錯誤,比如伺服器本身的錯誤,操作系統錯誤,甚至是突然斷電導致的錯誤。

  • 情況二:DBA可以在事務執行過程中手動輸入ROLLBACK語句結束當前事務的執行。
    以上情況出現,我們需要把數據改回原先的樣子,這個過程稱之為回滾。

每當我們要對一條記錄做改動時(這裡的改動可以指INSERT、DELETE、UPDATE),都需要"留一手"——把回滾時所需的東西記下來。比如:

  • 你插入一條記錄時,至少要把這條記錄的主鍵值記下來,之後回滾的時候只需要把這個主鍵值對應的記錄刪掉就好了。(對於每個INSERT, InnoDB存儲引擎會完成一個DELETE)

  • 你刪除了一條記錄,至少要把這條記錄中的內容都記下來,這樣之後回滾時再把由這些內容組成的記錄插入到表中就好了。(對於每個DELETE,InnoDB存儲引擎會執行一個INSERT)

  • 你修改了一條記錄,至少要把修改這條記錄前的舊值都記錄下來,這樣之後回滾時再把這條記錄更新為舊值就好了。(對於每個UPDATE,InnoDB存儲引擎會執行一個相反的UPDATE,將修改前的行放回去)

MySQL把這些為了回滾而記錄的這些內容稱之為撤銷日誌或者回滾日誌(即Undo Log)。註意,由於查詢操作(SELECT)並不會修改任何用戶記錄,所以在杳詢操作行時,並不需要記錄相應的Undo日誌

此外,Undo Log會產生Redo Log,也就是Undo Log的產生會伴隨著Redo Log的產生,這是因為Undo Log也需要持久性的保護。

Undo Log的功能

  • 提供數據回滾-原子性

    當事務回滾時或者資料庫崩潰時,可以利用Undo Log來進行數據回滾。
  • 多個行版本控制(MVCC)-隔離性

    即在InnoDB存儲引擎中MVCC的實現是通過Undo來完成。當用戶讀取一行記錄時,若該記錄已經被其他事務占用,當前事務可以通過Undo讀取之前的行版本信息,以此實現非鎖定讀取。

Undo Log的存儲結構

  • 回滾段與undo頁

InnoDB對Undo Log的管理採用段的方式,也就是回滾段(rollback segment)。每個回滾段記錄了1024個Undo Log segment,而在每個Undo Log segment段中進行Undo頁的申請。

InnoDB1.1版本之前(不包括1.1版本),只有一個rollback segment,因此支持同時線上的事務限製為1024。雖然對絕大多數的應用來說都已經夠用。

從1.1版本開始InnoDB支持最大128個rollback segment,故其支持同時線上的事務限制提高到了128*1024

mysql> show variables like 'innodb_undo_logs';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_undo_logs | 128   |
+------------------+-------+

雖然InnoDB1.1版本支持了128個rollback segment,但是這些rollback segment都存儲於共用表空間ibdata中。從lnnoDB1.2版本開始,可通過參數對rollback segment做進一步的設置。這些參數包括:

innodb_undo_directory:設置rollback segment文件所在的路徑。這意味著rollback segment可以存放在共用表空間以外的位置,即可以設置為獨立表空間。該參數的預設值為“./”,表示當前InnoDB存儲引擎的目錄。

innodb_undo_logs:設置rollback segment的個數,預設值為128。在InnoDB1.2版本中,該參數用來替換之前版本的參數innodb_rollback_segments。

innodb_undo_tablespaces:設置構成rollback segment文件的數量,這樣rollback segment可以較為平均地分佈在多個文件中。設置該參數後,會在路徑innodb_undo_directory看到undo為首碼的文件,該文件就代表rollback segment文件。

  • 回滾段與事務

1.每個事務只會使用一個回滾段(rollback segment),一個回滾段在同一時刻可能會服務於多個事務。

2.當一個事務開始的時候,會制定一個回滾段,在事務進行的過程中,當數據被修改時,原始的數據會被覆制到回滾段。

3.在回滾段中,事務會不斷填充盤區,直到事務結束或所有的空間被用完。如果當前的盤區不夠用,事務會在段中請求擴展下一個盤區,如果所有已分配的盤區都被用完,事務會覆蓋最初的盤區或者在回滾段允許的情況下擴展新的盤區來使用。

4.回滾段存在於Undo表空間中,在資料庫中可以存在多個Undo表空間,但同一時刻只能使用一個Undo表空間。

5.當事務提交時,InnoDB存儲引擎會做以下兩件事情:

1.將Undo Log放入列表中,以供之後的purge(清洗、清除)操作

2.判斷Undo Log所在的頁是否可以重用(低於3/4可以重用),若可以分配給下個事務使用

  • 回滾段中的數據分類

未提交的回滾數據(uncommitted undo information):該數據所關聯的事務並未提交,用於實現讀一致性,所以該數據不能被其他事務的數據覆蓋。

已經提交但未過期的回滾數據(committed undo information):該數據關聯的事務已經提交,但是仍受到undo retention參數的保持時間的影響。

事務已經提交並過期的數據(expired undo information):事務已經提交,而且數據保存時間已經超過undo retention參數指定的時間,屬於已經過期的數據。當回滾段滿了之後,會優先覆蓋"事務已經提交並過期的數據"。

  • Undo頁的重用

當我們開啟一個事務需要寫Undo log的時候,就得先去Undo Log segment中去找到一個空閑的位置,當有空位的時候,就去申請Undo頁,在這個申請到的Undo頁中進行Undo Log的寫入。我們知道MySQL預設一頁的大小是16k

為每一個事務分配一個頁,是非常浪費的(除非你的事務非常長),假設你的應用的TPS(每秒處理的事務數目)為1000,那麼1s就需要1000個頁,大概需要16M的存儲,1分鐘大概需要1G的存儲。如果照這樣下去除非MySQL清理的非常勤快,否則隨著時間的推移,磁碟空間會增長的非常快,而且很多空間都是浪費的。

於是Undo頁就被設計的可以重用了,當事務提交時,並不會立刻刪除Undo頁。因為重用,所以這個Undo頁可能混雜著其他事務的Undo Log。Undo Log在commit後,會被放到一個鏈表中,然後判斷Undo頁的使用空間是否小於3/4,如果小於3/4的話,則表示當前的Undo頁可以被重用,那麼它就不會被回收,其他事務的Undo Log可以記錄在當前Undo頁的後面。由於Undo Log是離散的,所以清理對應的磁碟空間時,效率不高。

  • Undo Log日誌的存儲機制


如上圖,可以看到,Undo Log日誌裡面不僅存放著數據更新前的記錄,還記錄著RowID事務ID回滾指針。其中事務ID每次遞增,回滾指針第一次如果是INSERT語句的話,回滾指針為NULL,第二次UPDATE之後的Undo Log的回滾指針就會指向剛剛那一條Undo Log日誌,以此類推,就會形成一條Undo Log的回滾鏈,方便找到該條記錄的歷史版本。

Undo Log的工作原理

在更新數據之前,MySQL會提前生成Undo Log日誌,當事務提交的時候,並不會立即刪除Undo Log,因為後面可能需要進行回滾操作,要執行回滾(ROLLBACK)操作時,從緩存中讀取數據。Undo Log日誌的刪除是通過通過後臺purge線程進行回收處理的。

  • 1、事務A執行UPDATE操作,此時事務還沒提交,會將數據進行備份到對應的Undo Buffer,然後由Undo Buffer持久化到磁碟中的Undo Log文件中,此時Undo Log保存了未提交之前的操作日誌,接著將操作的數據,也就是test表的數據持久保存到InnoDB的數據文件IBD。
  • 2、此時事務B進行查詢操作,直接從Undo Buffer緩存中進行讀取,這時事務A還沒提交事務,如果要回滾(ROLLBACK)事務,是不讀磁碟的,先直接從Undo Buffer緩存讀取。

Undo Log的類型

在InnoDB存儲引擎中,Undo Log分為:

  • insert Undo Log

    insert Undo Log是指在insert操作中產生的Undo Log。因為insert操作的記錄,只對事務本身可見,對其他事務不可見(這是事務隔離性的要求),故該Undo Log可以在事務提交後直接刪除。不需要進行purge操作。

  • update Undo Log

    update Undo Log記錄的是對delete和update操作產生的Undo Log。該Undo Log可能需要提供MVCC機制,因此不能在事務提交時就進行刪除。提交時放入Undo Log鏈表,等待purge線程進行最後的刪除。

Undo Log的生命周期

簡要生成過程

以下是Undo+Redo事務的簡化過程:

假設有2個數值,分別為A=1和B=2,然後將A修改為3,B修改為4

1. start transaction;
2.記錄A=1到Undo Log;
3. update A = 3;
4.記錄A=3 到Redo Log;
5.記錄B=2到Undo Log;
6. update B = 4;
7.記錄B = 4到Redo Log;
8.將Redo Log刷新到磁碟;
9. commit
  • 在1-8步驟的任意一步系統宕機,事務未提交,該事務就不會對磁碟上的數據做任何影響。

  • 如果在8-9之間宕機。

    • Redo Log 進行恢復
    • Undo Log 發現有事務沒完成進行回滾。
  • 若在9之後系統宕機,記憶體映射中變更的數據還來不及刷回磁碟,那麼系統恢復之後,可以根據Redo Log把數據刷回磁碟。

流程圖:

Undo Log的配置參數

innodb_max_undo_log_size:undo日誌文件的最大值,預設1GB,初始化大小10M

innodb_undo_log_truncate:標識是否開啟自動收縮Undo Log表空間的操作

innodb_undo_tablespaces:設置獨立表空間的個數,預設為0,標識不開啟獨立表空間,undo日誌保存在ibdata1中

innodb_undo_directory:undo日誌存儲的目錄位置
innodb_undo_logs: 回滾的個數 預設128

參考文章

  • 《MySQL是怎樣運行的--從根兒上理解MySQL》—小孩子4919

Enjoy GreatSQL

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • nginx平滑升級及nginx配置文件 nginx平滑升級並添加新功能 1.先獲取老版本的編譯信息 2.獲取新版本安裝包和功能包 3.配置新版本或功能,配置時加上老版本的編譯參數,然後添加新功能模塊 4.進行編譯,編譯完不進行安裝操作 5.備份老版本程式,使用複製的方法。在停掉老版本程式的進程,將新 ...
  • 作為電腦畢業的我,說起來慚愧,大學時候很多重要的專業課都沒好好聽過,慶幸的是,大學的很多教師課件我都有保存下來。這幾天,把《操作系統》拿起來看看,然後涉及到一些我認為重要的理論知識我會在這個專題都會記錄下來,這將會是一個持續的過程。 1、操作系統的目標 2、操作系統的作用 其中:四類資源是:處理器 ...
  • 最近谷歌官方宣稱由於使用人數少,關停了中國的翻譯服務,導致谷歌瀏覽器上的翻譯服務無法使用,當我們使用谷歌瀏覽器自帶翻譯功能時,會報出:無法翻譯此網頁,或者沒有翻譯反應。 在macOS下怎麼解決谷歌瀏覽器Chrome無法翻譯呢?下麵小編來教你快速解決。 1、打開終端(commond+空格 搜索“終端” ...
  • 一、CentOS 7.9 安裝 elasticsearch-7.8.1 地址 https://www.elastic.co https://www.elastic.co/cn/downloads/past-releases https://github.com/elastic https://git ...
  • 分離部署LNMP 環境說明: | 系統 | 主機名 | IP | 服務 | | | | | | | centos8 | nginx | 192.168.111.141 | nginx | | centos8 | mysql | 192.168.111.142 | mysql | | centos8 ...
  • nginx 一、nginx簡介 nginx(發音同engine x)是一款輕量級的Web伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,併在一個BSD-like協議下發行。 nginx由俄羅斯的程式設計師Igor Sysoev所開發,最初供俄國大型的入口網站及搜尋引擎Rambler ...
  • Redis有3種實現持久化的方式:AOF日誌、RDB快照、混合持久化 Redis寫入AOF日誌的過程 Redis執行完寫操作命令後,將命令追加到server.aof_buf緩衝區 通過write()系統調用,將aof_buf緩衝區的數據寫入到AOF文件 數據被拷貝到了內核緩衝區page cache ...
  • 一、MySQL資料庫內置系統表 mysql5.7之後的版本自帶資料庫為 1.information_schema資料庫 這個庫在mysql中就是個信息資料庫,它保存著mysql伺服器所維護的所有其他資料庫的信息,包括了資料庫名,表名,欄位名等。在註入中,infromation_schema庫的作用無 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...