欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL日志專項(xiàng)之redo log和undo log介紹

 更新時(shí)間:2022年08月24日 11:41:38   作者:清風(fēng)拂來水波不興  
MySQL日志記錄了MySQL數(shù)據(jù)庫(kù)日常操作和錯(cuò)誤信息,MySQL有不同類型的日志文件(各自存儲(chǔ)了不同類型的日志),從日志當(dāng)中可以查詢到MySQL數(shù)據(jù)庫(kù)的運(yùn)行情況、用戶操作、錯(cuò)誤信息等

Redo Log

REDO LOG稱為重做日志 ,當(dāng)MySQL服務(wù)器意外崩潰或者宕機(jī)后,保證已經(jīng)提交的事務(wù)持久化到磁盤中(持久性)。

InnoDB是以頁為單位去操作記錄的,增刪改查都會(huì)加載整個(gè)頁到buffer pool中(磁盤->內(nèi)存),事務(wù)中的修改操作并不是直接修改磁盤中的數(shù)據(jù),而是先修改內(nèi)存中buffer pool中的數(shù)據(jù),后臺(tái)線程每隔一段時(shí)間再異步刷新到磁盤中。

buffer pool:可存放索引、數(shù)據(jù),可加速讀寫,直接在內(nèi)存中操作數(shù)據(jù)頁,有專門的線程去把buffer pool中的臟頁寫入磁盤。

為什么不直接修改磁盤中的數(shù)據(jù)?

因?yàn)橹苯有薷拇疟P數(shù)據(jù)的話,它是隨機(jī)IO,修改的數(shù)據(jù)分布在磁盤中不同的位置,需要來回的查找,所以命中率低,消耗大,而且一個(gè)小小的修改就不得不將整個(gè)頁刷新到磁盤,利用率低;

與之相對(duì)的是順序IO,磁盤的數(shù)據(jù)分布在磁盤的一塊,所以省去了查找的過程,節(jié)省尋道時(shí)間。

使用后臺(tái)線程以一定的頻率去刷新磁盤可以降低隨機(jī)IO的頻率,增加吞吐量,這是使用buffer pool的根本原因。

修改內(nèi)存再異步同步到磁盤的問題:

因?yàn)閎uffer pool是在內(nèi)存中的區(qū)域,系統(tǒng)意外崩潰的話數(shù)據(jù)有可能會(huì)丟失,有些臟數(shù)據(jù)可能會(huì)來不及刷新到磁盤,事務(wù)的持久性得不到保證。因此,引入了redo log。修改數(shù)據(jù)時(shí),額外記錄一次日志,內(nèi)容是xx頁xx偏移量發(fā)生了xx變化,當(dāng)系統(tǒng)崩潰時(shí)可以根據(jù)日志內(nèi)容進(jìn)行恢復(fù)。

寫日志和直接刷新磁盤的區(qū)別是:寫日志是追加寫入,順序IO,速度更快,且寫入的內(nèi)容相對(duì)更小

redo log由兩部分組成:

  1. redo log buffer(內(nèi)存層面,默認(rèn)16M,通過innodb_log_buffer_size參數(shù)可修改)
  2. redo log file(持久化的,磁盤層面)

修改操作大致過程:

第1步:先將原始數(shù)據(jù)從磁盤中讀入內(nèi)存中來,修改數(shù)據(jù)的內(nèi)存拷貝,產(chǎn)生臟數(shù)據(jù)

第2步:生成一條重做日志并寫入redo log buffer,記錄的是數(shù)據(jù)被修改后的值

第3步:默認(rèn)在事務(wù)提交后將redo log buffer中的內(nèi)容刷新到redo log file,對(duì)redo log file采用追加寫的方式

第4步:定期將內(nèi)存中修改的數(shù)據(jù)刷新到磁盤中(這里說的是那些還沒及時(shí)被后臺(tái)線程刷盤的臟數(shù)據(jù))

通常所說的Write-Ahead Log(預(yù)先日志持久化)指的是在持久化一個(gè)數(shù)據(jù)頁之前,先將內(nèi)存中相應(yīng)的日志頁持久化。

redo log的好處:

  • 減少了磁盤刷新頻率
  • redo log占用空間小
  • redo log寫入速度快

redo log一定能保證事務(wù)的持久性嗎?

不一定,這要根據(jù)redo log的刷盤策略決定,因?yàn)閞edo log buffer同樣是在內(nèi)存中,如果提交事務(wù)之后,redo log buffer還沒來得及將數(shù)據(jù)刷新到redo log file進(jìn)行持久化,此時(shí)發(fā)生宕機(jī)照樣會(huì)丟失數(shù)據(jù)。如何解決?刷盤策略。

redo log刷盤策略

InnoDB中給出了innodb_flush_log_at_trx_commit參數(shù)控制redo log buffer刷新到redo log file時(shí)的三種策略:

  • 值為0:開啟一個(gè)后臺(tái)線程,每1s刷新一次到磁盤中,提交事務(wù)時(shí)就不需要進(jìn)行刷新了
  • 值為1:commit時(shí)再進(jìn)行同步刷新(默認(rèn)值),真正保證數(shù)據(jù)的持久性
  • 值為2:commit的時(shí)候,只是刷新進(jìn)os的內(nèi)核緩沖區(qū),具體的刷盤時(shí)機(jī)不確定

值為0的情況:

因?yàn)橛?s的間隔,所以最壞情況下會(huì)丟失1秒的數(shù)據(jù)。

值為1的情況:

commit時(shí)需要先主動(dòng)刷新redo log buffer到redo log file,如果中途宕機(jī)了,事務(wù)也就失敗了,不會(huì)有任何損失,真正能保證事務(wù)的持久性。但是效率最差。

值為2的情況:是根據(jù)os決定。

可以調(diào)整為0或2提高事務(wù)的性能,但是喪失了ACID特性

其他參數(shù)

  • innodb_log_group_home_dir:指定 redo log文件組所在的路徑,默認(rèn)值為 ./ ,表示在數(shù)據(jù)庫(kù)的數(shù)據(jù)目錄下。MySQL的默認(rèn)數(shù)據(jù)目錄下默認(rèn)有兩個(gè)名為ib_logfile0和ib_logfile1的文件,log buffer中的日志默認(rèn)情況下就是刷新到這兩個(gè)磁盤文件中。
  • innodb_log_files_in_group:指明redo log file的個(gè)數(shù),命名方式如:ib_logfile0,iblogfile1... iblogfilen。默認(rèn)2個(gè),最大100個(gè)。
  • innodb_log_file_size:?jiǎn)蝹€(gè) redo log 文件設(shè)置大小,默認(rèn)值為 48M 。

Undo Log

undo log用于保證事務(wù)的原子性和一致性。作用有兩個(gè):①提供回滾操作 ②多版本控制MVVC

回滾操作

前面redo log中說過,后臺(tái)線程會(huì)不定時(shí)的去刷新buffer pool中的數(shù)據(jù)到磁盤,但是如果該事務(wù)執(zhí)行期間出現(xiàn)各種錯(cuò)誤(宕機(jī))或者執(zhí)行rollback語句,那么前面刷進(jìn)去的操作都是需要回滾的,保證原子性,undo log就是提供事務(wù)回滾的。

MVVC

當(dāng)讀取的某一行被其他事務(wù)鎖定時(shí),它可以從undo log中分析出該行記錄以前的數(shù)據(jù)版本是怎樣的,從而讓用戶能夠讀取到當(dāng)前事務(wù)操作之前的數(shù)據(jù)——快照讀。

快照讀:SQL讀取的數(shù)據(jù)是歷史版本,不用加鎖,普通的SELECT就是快照讀。

undo log的組成部分:

  • 當(dāng)insert記錄的時(shí)候,必須將該記錄的主鍵值記錄下來,這樣才可以回滾時(shí)刪除該數(shù)據(jù)。
  • 當(dāng)update記錄的時(shí)候,必須將修改的舊值全部記錄下來,回滾時(shí)更新為舊值即可。
  • 當(dāng)delete的時(shí)候,必須將所有的記錄都記錄下來,回滾時(shí)再重新插入該內(nèi)容的記錄。

select操作不會(huì)產(chǎn)生undo log

回滾段與undo頁

在InnoDB存儲(chǔ)引擎中,undo log使用rollback segment回滾段進(jìn)行存儲(chǔ),每隔回滾段包含了1024個(gè)undo log segment。 MySQL5.5之后,一共有128個(gè)回滾段。即總共可以記錄128 * 1024個(gè)undo操作。

每個(gè)事務(wù)只會(huì)使用一個(gè)回滾段,一個(gè)回滾段在同一時(shí)刻可能會(huì)服務(wù)于多個(gè)事務(wù)。

事務(wù)提交后不能立即刪除該undo log,可能有些事務(wù)會(huì)想要讀取之前的數(shù)據(jù)版本(快照讀)。所以事務(wù)提交時(shí)將undo log放入一個(gè)鏈表中,稱為版本鏈,undo log的刪除與否由一個(gè)稱為purge的線程判斷。

Undo類型

undo log分為:

insert undo log

因?yàn)閕nsert操作的記錄,只對(duì)事務(wù)本身可見,對(duì)其他事務(wù)不可見(這是事務(wù)隔離性的要求),故該undo log可以在事務(wù)提交后直接刪除。不需要進(jìn)行purge操作。

update undo log

update undo log記錄的是對(duì)delete和update操作產(chǎn)生的undo log。該undo log可能需要提供MVCC機(jī)制,因此不能在事務(wù)提交時(shí)就進(jìn)行刪除。提交時(shí)放入undo log鏈表,等待purge線程進(jìn)行最后的刪除。

undo log的生命周期

假設(shè)有2個(gè)數(shù)值,分別為A=1和B=2,然后某個(gè)事務(wù)將A修改為3,B修改為4,修改過程可簡(jiǎn)化為:

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步驟的任意一步系統(tǒng)宕機(jī),事務(wù)未提交,該事務(wù)就不會(huì)對(duì)磁盤上的數(shù)據(jù)做任何影響。
  • 如果在8-9之間宕機(jī),恢復(fù)之后可以選擇回滾,也可以選擇繼續(xù)完成事務(wù)提交,因?yàn)榇藭r(shí)redo log已經(jīng)持久化。
  • 若在9之后系統(tǒng)宕機(jī),內(nèi)存映射中變更的數(shù)據(jù)還來不及刷回磁盤,那么系統(tǒng)恢復(fù)之后,可以根據(jù)redo log把數(shù)據(jù)刷回磁盤。

詳細(xì)生成過程

對(duì)于InnoDB引擎來說,每個(gè)行記錄除了記錄本身的數(shù)據(jù)之外,還有幾個(gè)隱藏的列:

  • DB_ROW_ID∶記錄的主鍵id。
  • DB_TRX_ID:事務(wù)ID,當(dāng)對(duì)某條記錄發(fā)生修改時(shí),就會(huì)將這個(gè)事務(wù)的Id記錄其中。
  • DB_ROLL_PTR︰回滾指針,版本鏈中的指針。

當(dāng)我們執(zhí)行INSERT時(shí):

begin;
INSERT INTO user (name) VALUES ('tom');

插入的數(shù)據(jù)都會(huì)生成一條insert undo log,并且數(shù)據(jù)的回滾指針會(huì)指向它。undo log會(huì)記錄undo log的序號(hào)、插入主鍵的列和值...,那么在進(jìn)行rollback的時(shí)候,通過主鍵直接把對(duì)應(yīng)的數(shù)據(jù)刪除即可。

當(dāng)我們執(zhí)行UPDATE時(shí):

對(duì)于更新的操作會(huì)產(chǎn)生update undo log,并且會(huì)分更新主鍵的和不更新主鍵的,假設(shè)現(xiàn)在執(zhí)行:

UPDATE user SET name='Sun' WHERE id=1;

這時(shí)會(huì)把新的undo log記錄加入到版本鏈中,它的undo no是1,并且新的undo log的回滾指針會(huì)指向老的undo log (undo no=0)。

假設(shè)現(xiàn)在執(zhí)行:

UPDATE user SET id=2 WHERE id=1;

對(duì)于更新主鍵的操作,會(huì)先把原來的數(shù)據(jù)deletemark標(biāo)識(shí)打開,這時(shí)并沒有真正的刪除數(shù)據(jù),真正的刪除會(huì)交給清理線程去判斷,然后在后面插入一條新的數(shù)據(jù),新的數(shù)據(jù)也會(huì)產(chǎn)生undo log,并且undo log的序號(hào)會(huì)遞增。

可以發(fā)現(xiàn)每次對(duì)數(shù)據(jù)的變更都會(huì)產(chǎn)生一個(gè)undo log,當(dāng)一條記錄被變更多次時(shí),那么就會(huì)產(chǎn)生多條undo log,undo log記錄的是變更前的日志,并且每個(gè)undo log的序號(hào)是遞增的,那么當(dāng)要回滾的時(shí)候,按照序號(hào)依次向前推,就可以找到我們的原始數(shù)據(jù)了。

undo log是如何回滾的

以上面的例子來說,假設(shè)執(zhí)行rollback,那么對(duì)應(yīng)的流程應(yīng)該是這樣:

1. 通過undo no=3的日志把id=2的數(shù)據(jù)刪除

2. 通過undo no=2的日志把id=1的數(shù)據(jù)的deletemark還原成0

3. 通過undo no=1的日志把id=1的數(shù)據(jù)的name還原成Tom

4. 通過undo no=0的日志把id=1的數(shù)據(jù)刪除

MySQL MVVC多版本并發(fā)控制

擴(kuò)展

bin log

binlog即binary log,二進(jìn)制日志文件,也叫作變更日志(update log)。它記錄了數(shù)據(jù)庫(kù)所有執(zhí)行的更新語句。

binlog主要應(yīng)用場(chǎng)景:

  • 數(shù)據(jù)恢復(fù):如果MySQL意外停止,可以通過該日志進(jìn)行恢復(fù)、備份
  • 數(shù)據(jù)復(fù)制:master把它的二進(jìn)制日志傳遞給slaves來達(dá)到master-slave數(shù)據(jù)的一致性
show variables like '%log_bin%';

查看bin log日志:

mysqlbinlog -v "/var/lib/mysql/binlog/xxx.000002"

使用日志恢復(fù)數(shù)據(jù):

mysqlbinlog [option] filename|mysql –uuser -ppass;

刪除二進(jìn)制日志:

PURGE {MASTER | BINARY} LOGS TO ‘指定日志文件名'
PURGE {MASTER | BINARY} LOGS BEFORE ‘指定日期'

寫入時(shí)機(jī)

事務(wù)執(zhí)行過程中,先把日志寫到bin log cache ,事務(wù)提交的時(shí)候,再把binlog cache寫到binlog文件中。因?yàn)橐粋€(gè)事務(wù)的binlog不能被拆開,無論這個(gè)事務(wù)多大,也要確保一次性寫入,所以系統(tǒng)會(huì)給每個(gè)線程分配一個(gè)塊內(nèi)存作為binlog cache。

binlog與redo log對(duì)比

  • redo log是物理日志,記錄內(nèi)容是“在xx數(shù)據(jù)頁做了xx修改”,屬于InnoDB存儲(chǔ)引擎層產(chǎn)生的。
  • 而binlog是邏輯日志,記錄內(nèi)容是語句的原始邏輯,類似于給ID=2這一行的c字段加1,屬于服務(wù)層。

兩個(gè)側(cè)重點(diǎn)也不同, redo log讓InnoDB有了崩潰恢復(fù)的能力,binlog保證了MySQL集群架構(gòu)的數(shù)據(jù)一致性。

兩階段提交

在執(zhí)行更新語句過程,會(huì)記錄redo log與binlog兩塊日志,以基本的事務(wù)為單位,redo log在事務(wù)執(zhí)行過程中可以不斷寫入,而binlog只有在提交事務(wù)時(shí)才寫入,所以redo log與binlog的寫入時(shí)機(jī)不一樣。

redo log與binlog兩份日志之間的邏輯不一致,會(huì)出現(xiàn)什么問題?

以u(píng)pdate語句為例,假設(shè)id=2的記錄,字段c值是0,把字段c值更新成1,SQL語句為update T set c=1 where id=2。

假設(shè)執(zhí)行過程中寫完redo log日志后,binlog日志寫期間發(fā)生了異常,會(huì)出現(xiàn)什么情況呢?

由于binlog沒寫完就異常,這時(shí)候binlog里面沒有對(duì)應(yīng)的修改記錄。因此,之后用binlog日志恢復(fù)數(shù)據(jù)或者slave讀取master的binlog時(shí),就會(huì)少這一次更新,恢復(fù)出來的這一行c值是0,而原庫(kù)因?yàn)閞edo log日志恢復(fù),這一行c值是1,最終數(shù)據(jù)不一致。

為了解決兩份日志之間的邏輯一致問題,InnoDB存儲(chǔ)引擎使用兩階段提交方案。將redo log拆成了兩個(gè)步驟prepare和commit,這就是兩階段提交。

讓redo log和bin log最終的提交綁定到一起,前面說過的,事務(wù)commit時(shí)默認(rèn)需要讓redo log先同步完才算commit成功,所以如果綁定到一起的話,bin log也具有該特性了,就保證了數(shù)據(jù)不會(huì)丟失。

使用兩階段提交后,寫入binlog時(shí)發(fā)生異常也不會(huì)有影響,因?yàn)镸ySQL根據(jù)redo log日志恢復(fù)數(shù)據(jù)時(shí)發(fā)現(xiàn)redo log還處于prepare階段,并且沒有對(duì)應(yīng)binlog日志,就會(huì)提交失敗,回滾數(shù)據(jù)。

另一個(gè)場(chǎng)景,redo log的commit階段發(fā)生異常,那會(huì)不會(huì)回滾事務(wù)呢?

并不會(huì)回滾事務(wù),它會(huì)執(zhí)行上圖框住的邏輯,雖然redo log是處于prepare階段,但是能通過事務(wù)id找到對(duì)應(yīng)的binlog日志,所以MySQL認(rèn)為是完整的,就會(huì)提交事務(wù)恢復(fù)數(shù)據(jù)。

到此這篇關(guān)于MySQL日志專項(xiàng)之redo log和undo log介紹的文章就介紹到這了,更多相關(guān)MySQL redo log與undo log內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL 利用frm文件和ibd文件恢復(fù)表數(shù)據(jù)

    MySQL 利用frm文件和ibd文件恢復(fù)表數(shù)據(jù)

    這篇文章主要介紹了MySQL 利用frm文件和ibd文件恢復(fù)表數(shù)據(jù),幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下
    2021-03-03
  • ubuntu下mysql?8.0.28 安裝配置方法圖文教程

    ubuntu下mysql?8.0.28 安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了ubuntu下mysql?8.0.28安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • MySQL查看版本的五種方法總結(jié)

    MySQL查看版本的五種方法總結(jié)

    在日常項(xiàng)目開發(fā)過程中,我們經(jīng)常要連接自己的數(shù)據(jù)庫(kù),此時(shí)不知道數(shù)據(jù)庫(kù)的版本是萬萬不可的,下面這篇文章主要給大家介紹了關(guān)于MySQL查看版本的五種方法,需要的朋友可以參考下
    2023-02-02
  • MySQL?中定位?DDL?被阻塞的問題及解決方案

    MySQL?中定位?DDL?被阻塞的問題及解決方案

    DDL 被阻塞了,如何找到阻塞它的 SQL?下面,就這個(gè)問題,給一個(gè)清晰明了、拿來即用的解決方案,本文通過一個(gè)簡(jiǎn)單的demo給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2022-01-01
  • Mybatis的where標(biāo)簽使用總結(jié)梳理

    Mybatis的where標(biāo)簽使用總結(jié)梳理

    這篇文章主要介紹了Mybatis的where標(biāo)簽使用總結(jié)梳理,文章通過將Mybatis中where標(biāo)簽的基本使用形式展開where標(biāo)簽小技巧以及容易踩到的坑進(jìn)行總結(jié)梳理,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • 了解MySQL查詢語句執(zhí)行過程(5大組件)

    了解MySQL查詢語句執(zhí)行過程(5大組件)

    這篇文章主要介紹了了解MySQL查詢語句執(zhí)行過程(5大組件),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Mysql中的join操作

    Mysql中的join操作

    這篇文章主要介紹了Mysql join操作的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • mysql5.7.13 環(huán)境搭建教程(解壓縮版)

    mysql5.7.13 環(huán)境搭建教程(解壓縮版)

    這篇文章主要為大家詳細(xì)介紹了mysql解壓縮版環(huán)境搭建教程,具有一定的實(shí)用性,感興趣的小伙伴們可以參考一下
    2016-07-07
  • Mysql中in和exists的區(qū)別?&?not?in、not?exists、left?join的相互轉(zhuǎn)換問題

    Mysql中in和exists的區(qū)別?&?not?in、not?exists、left?join的相互轉(zhuǎn)換問題

    這篇文章主要介紹了Mysql中in和exists的區(qū)別?&?not?in、not?exists、left?join的相互轉(zhuǎn)換,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • SQL中日期與字符串互相轉(zhuǎn)換操作實(shí)例

    SQL中日期與字符串互相轉(zhuǎn)換操作實(shí)例

    我們經(jīng)常出于某種目的需要使用各種各樣的日期格式,當(dāng)然我們可以使用字符串操作來構(gòu)造各種日期格式,下面這篇文章主要給大家介紹了關(guān)于SQL中日期與字符串互相轉(zhuǎn)換操作的相關(guān)資料,需要的朋友可以參考下
    2022-10-10

最新評(píng)論