MySQL日誌之redo log和undo log的知識點有哪些
Redo Log
#REDO LOG稱為重做日誌,當MySQL伺服器意外崩潰或當機後,保證已經提交的交易持久化到磁碟中(持久性)。
InnoDB是以頁為單位去操作記錄的,增刪改查都會加載整個頁到buffer pool中(磁碟->內存),事務中的修改操作並不是直接修改磁碟中的數據,而是先修改記憶體中buffer pool中的數據,後台執行緒每隔一段時間再異步刷新到磁碟中。
buffer pool:可存放索引、數據,可加速讀寫,直接在記憶體中操作資料頁,有專門的執行緒去把buffer pool中的髒頁寫入磁碟。
為什麼不直接修改磁碟中的資料?
因為直接修改磁碟資料的話,它是隨機IO,修改的資料分佈在磁碟中不同的位置,需要來回的查找,所以命中率低,消耗大,而且一個小小的修改就不得不將整個頁刷新到磁碟,利用率低;
與之相對的是順序IO,磁碟的資料分佈在磁碟的一塊,所以省去了查找的過程,節省尋道時間。
使用後台執行緒以一定的頻率去刷新磁碟可以降低隨機IO的頻率,增加吞吐量,這是使用buffer pool的根本原因。
修改記憶體再異步同步到磁碟的問題:
因為buffer pool是在記憶體中的區域,系統意外崩潰的話資料有可能會遺失,有些髒資料可能會來不及刷新到磁碟,事務的持久性得不到保證。因此,引入了redo log。修改資料時,額外記錄一次日誌,內容是xx頁xx偏移量發生了xx變化,當系統崩潰時可以根據日誌內容進行恢復。
寫日誌和直接刷新磁碟的差別是:寫日誌是追加寫入,順序IO,速度更快,且寫入的內容相對更小
redo log由兩部分組成:
redo log buffer(記憶體層面,預設16M,透過innodb_log_buffer_size參數可修改)
redo log file(持久的,磁碟層面)
修改操作大致流程:
#第1步:先將原始資料從磁碟中讀入記憶體中來,修改資料的記憶體拷貝,產生髒資料
第2步:產生一則重做日誌並寫入redo log buffer,記錄的是資料被修改後的值
第3步:預設在交易提交後將redo log buffer中的內容刷新到redo log file,對redo log file採用追加寫的方式
第4步:定期將記憶體中修改的資料刷新到磁碟中(這裡說的是那些還沒及時被後台線程刷盤的髒數據)
通常所說的Write-Ahead Log(預先日誌持久化)指的是在持久化一個數據頁之前,先將記憶體中對應的日誌頁持久化。
redo log的好處:
減少了磁碟重新整理頻率
redo log佔用空間小
redo log寫入速度快
redo log一定能保證交易的持久性嗎?
不一定,這要根據redo log的刷盤策略決定,因為redo log buffer同樣是在內存中,如果提交事務之後,redo log buffer還沒來得及將數據刷新到redo log file進行持久化,此時發生宕機照樣會遺失資料。如何解決?刷盤策略。
redo log刷盤策略
InnoDB中給出了innodb_flush_log_at_trx_commit參數控制redo log buffer刷新到redo log file時的三種策略:
值為0:開啟一個後台線程,每1s刷新一次到磁碟中,提交事務時就不需要進行刷新了
值為1:commit時再進行同步刷新(預設值),真正保證資料的持久性
值為2:commit的時候,只是刷新進os的核心緩衝區,具體的刷盤時機不確定
值為0的情況:
因為有1s的間隔,所以最壞情況下會遺失1秒的資料。
值為1的情況:
commit時需要先主動刷新redo log buffer到redo log file,如果中途宕機了,交易也就失敗了,不會有任何損失,真正能保證事務的持久性。但是效率最差。
值為2的情況:是根據os決定。
可以調整為0或2提高事務的效能,但是喪失了ACID特性
其他參數
innodb_log_group_home_dir:指定 redo log檔案群組所在的路徑,預設值為 ./ ,表示在資料庫的資料目錄下。 MySQL的預設資料目錄下預設有兩個名為ib_logfile0和ib_logfile1的文件,log buffer中的日誌預設有刷新到這兩個磁碟檔案。
innodb_log_files_in_group:指明redo log file的數量,命名方式如:ib_logfile0,iblogfile1... iblogfilen。預設2個,最大100個。
預設情況下,innodb_log_file_size的大小設定為48M,用於單一redo log檔案的大小設定。
Undo Log
undo log用來保證交易的原子性和一致性。作用有兩個:①提供回滾操作②多版本控制MVVC
回滾操作
前面redo log中說過,後台執行緒會不定時的去刷新buffer pool中的數據到磁碟,但是如果該事務執行期間出現各種錯誤(宕機)或者執行rollback語句,那麼前面刷進去的操作都是需要回滾的,保證原子性,undo log就是提供事務回滾的。
MVVC
當讀取的某一行被其他事務鎖定時,它可以從undo log分析出該行記錄先前的資料版本是怎樣的,從而讓使用者能夠讀取到目前事務操作之前的資料——快照讀取。
快照讀:SQL讀取的資料是歷史版本,不用加鎖,普通的SELECT就是快照讀。
undo log的組成部分:
當insert記錄的時候,必須將該記錄的主鍵值記錄下來,這樣才可以回滾時刪除該數據。
當update記錄的時候,必須將修改過的舊值全部記錄下來,回滾時更新為舊值即可。
當delete的時候,必須將所有的記錄都記錄下來,回滾時再重新插入該內容的記錄。
select作業不會產生undo log
回滾段與undo頁
在InnoDB儲存引擎中,undo log使用rollback segment回滾段進行存儲,每隔回滾段包含了1024個undo log segment。 MySQL5.5之後,總共有128個回滾段。即總共可以記錄128 * 1024個undo操作。
每個交易只會使用一個回滾段,一個回滾段在同一時刻可能會服務多個交易。
刪除undo log無法立即執行在提交交易後,因為有些事務可能想要讀取先前的資料版本(快照讀取)。所以事務提交時將undo log放入一個鍊錶中,稱為版本鏈,undo log的刪除與否由一個稱為purge的執行緒判斷。
Undo類型
undo log分為:
insert undo log
因為insert操作的記錄,只對事務本身可見,對其他事務不可見(這是事務隔離性的要求),故該undo log可以在交易提交後直接刪除。不需要進行purge操作。
update undo log
Undo logs record the changes made to delete and update operations.。為了支援MVCC機制,因此無法在交易提交時立即刪除undo log。在提交時,將其加入撤銷日誌鍊錶,等待清理執行緒進行最終的刪除。
undo log的生命週期
假設有2個數值,分別為A=1和B=2,然後某個交易將A修改為3,B修改為4,修改過程可簡化為:
1.begin
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已經持久化。
若在9之後系統當機,記憶體對映中變更的資料還沒來得及刷回磁碟,那麼系統復原之後,可以依照redo log把資料刷回磁碟。
詳細產生過程
對於InnoDB引擎來說,每個行記錄除了記錄本身的資料之外,還有幾個隱藏的欄位:
DB_ROW_ID∶記錄的主鍵id。
DB_TRX_ID:交易ID,當對某筆記錄發生修改時,就會將這個交易的Id記錄其中。
DB_ROLL_PTR︰回滾指針,版本鏈中的指針。
當我們執行INSERT:
begin; INSERT INTO user (name) VALUES ('tom');
每次插入資料都會建立一個插入操作的撤銷日誌,資料的回溯指標會指向此日誌。 undo log會記錄undo log的序號、插入主鍵的列和值...,那麼在進行rollback的時候,透過主鍵直接把對應的資料刪除即可。
當我們執行UPDATE時:
執行更新操作時,會產生更新撤銷日誌,其中包含更新主鍵和不更新主鍵兩種情況。假設現在進行更新操作:
UPDATE user SET name='Sun' WHERE id=1;
這時會把新的undo log記錄加入到版本鏈中,它的undo no是1,並且新的undo log的回滾指標會指向舊的undo log (undo no=0)。
假設現在執行:
UPDATE user SET id=2 WHERE id=1;
對於更新主鍵的操作,會先把原來的資料deletemark標識打開,這時並沒有真正的刪除數據,真正的刪除會交給清理線程去判斷,然後在後面插入一條新的數據,新的數據也會產生undo log,並且undo log的序號會遞增。
可以發現每次對資料的變更都會產生一個undo log,當一筆記錄被變更多次時,那麼就會產生多個undo log,undo log記錄的是變更前的日誌,並且每個undo log的序號是遞增的,那麼當要回滾的時候,按照序號依序向前推,就可以找到我們的原始資料了。
undo log是如何回滾的
以上面的範例來說,假設執行rollback,那麼對應的流程應該是這樣:
1. 透過undo no= 3的日誌把id=2的資料刪除
2. 透過undo no=2的日誌把id=1的資料的deletemark還原成0
3. 透過undo no=1的日誌把id=1的資料的name還原成Tom
4. 透過undo no=0的日誌把id=1的資料刪除
MySQL MVVC多版本並發控制
擴展
bin log
Binary log, also known as update log, is a type of log file in binary format that records changes made to a database.。它記錄了資料庫所有執行的更新語句。
binlog主要應用場景:
資料復原:如果MySQL意外停止,可以透過此日誌進行復原、備份
- # #資料複製:master把它的二進位日誌傳遞給slaves來達到master-slave資料的一致性
show variables like '%log_bin%';
mysqlbinlog -v "/var/lib/mysql/binlog/xxx.000002"
mysqlbinlog [option] filename|mysql –uuser -ppass;
PURGE {MASTER | BINARY} LOGS TO ‘指定日志文件名' PURGE {MASTER | BINARY} LOGS BEFORE ‘指定日期'
- #InnoDB儲存引擎層產生的redo log是一種實體日誌,用於記錄“對於哪些資料頁進行了什麼樣的修改」。
- 而binlog是邏輯日誌,記錄內容是語句的原始邏輯,類似給ID=2這一行的c欄位加1,屬於服務層。
InnoDB儲存引擎採用雙階段提交方案來處理兩份日誌之間的邏輯一致性問題。兩階段提交是指將redo log分為prepare和commit兩個步驟處理。
讓redo log和bin log最終的提交綁定到一起,前面說過的,事務commit時預設需要讓redo log先同步完才算commit成功,所以如果綁定到一起的話,bin log也具有該特性了,就保證了資料不會遺失。
使用兩階段提交後,寫入binlog時發生異常也會有影響,因為MySQL根據redo log日誌復原資料時發現redo log仍處於prepare階段,且沒有對應binlog日誌,就會提交失敗,回溯資料。
另一個場景,redo log的commit階段發生異常,那會不會回溯事務呢?
並不會回滾事務,它會執行上圖框住的邏輯,雖然redo log是處於prepare階段,但是能透過交易id找到對應的binlog日誌,所以MySQL認為是完整的,就會提交交易恢復資料。
以上是MySQL日誌之redo log和undo log的知識點有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

在開發一個小型應用時,我遇到了一個棘手的問題:需要快速集成一個輕量級的數據庫操作庫。嘗試了多個庫後,我發現它們要么功能過多,要么兼容性不佳。最終,我找到了minii/db,這是一個基於Yii2的簡化版本,完美地解決了我的問題。
