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

MySQL系列之redo log、undo log和binlog詳解

 更新時(shí)間:2020年12月26日 09:28:18   作者:曹自標(biāo)  
這篇文章主要介紹了MySQL系列之redo log、undo log和binlog詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

事務(wù)的實(shí)現(xiàn)

redo log保證事務(wù)的持久性,undo log用來(lái)幫助事務(wù)回滾及MVCC的功能。

InnoDB存儲(chǔ)引擎體系結(jié)構(gòu)

redo log

Write Ahead Log策略

事務(wù)提交時(shí),先寫(xiě)重做日志再修改頁(yè);當(dāng)由于發(fā)生宕機(jī)而導(dǎo)致數(shù)據(jù)丟失時(shí),就可以通過(guò)重做日志來(lái)完成數(shù)據(jù)的恢復(fù)。

  • InnoDB首先將重做日志信息先放到重做日志緩存
  • 按一定頻率刷新到重做日志文件

重做日志文件: 在默認(rèn)情況,InnoDB存儲(chǔ)引擎的數(shù)據(jù)目錄下會(huì)有兩個(gè)名為ib_logfile1和ib_logfile2的文件。每個(gè)InnoDB存儲(chǔ)引擎至少有1個(gè)重做日志文件組(group),每個(gè)文件組下至少有2個(gè)重做日志文件。

下面圖一,很好說(shuō)明重做日志組以循環(huán)寫(xiě)入方式運(yùn)行,InnoDB存儲(chǔ)引擎先寫(xiě)ib_logfile1,當(dāng)達(dá)到文件最后時(shí),會(huì)切換至重做日志文件ib_logfile2.

而圖2,增加一個(gè)OS Buffer,有助于理解fsync過(guò)程。

關(guān)于log group,稱(chēng)為重做日志組,是一個(gè)邏輯上的概念。InnoDB存儲(chǔ)引擎實(shí)際只有一個(gè)log group。

log group中第一個(gè)redo log file,其前2KB部分保存4個(gè)512字節(jié)大小塊:

重做日志緩沖刷新到磁盤(pán)

下面三種情況刷新:

  • Master Thread每一秒將重做日志緩沖刷新到重做日志文件
  • 每個(gè)事務(wù)提交時(shí)會(huì)將重做日志緩沖刷新到重做日志文件
  • 當(dāng)重做日志緩沖池剩余空間小于1/2時(shí),重做日志刷新到重做日志文件

補(bǔ)充上述三種情況第二種,觸發(fā)寫(xiě)磁盤(pán)過(guò)程由參數(shù)innodb_flush_log_at_trx_commit控制,表示提交(commit)操作時(shí),處理重做日志的方式。

參數(shù)innodb_flush_log_at_trx_commit有效值有0、1、2

  • 0表示當(dāng)提交事務(wù)時(shí),并不將事務(wù)的重做日志寫(xiě)入磁盤(pán)上日志文件,而是等待主線程每秒刷新。
  • 1表示在執(zhí)行commit時(shí)將重做日志緩沖同步寫(xiě)到磁盤(pán),即伴有fsync的調(diào)用
  • 2表示將重做日志異步寫(xiě)到磁盤(pán),即寫(xiě)到文件系統(tǒng)的緩存中。不保證commit時(shí)肯定會(huì)寫(xiě)入重做日志文件。

0,當(dāng)數(shù)據(jù)庫(kù)發(fā)生宕機(jī)時(shí),部分日志未刷新到磁盤(pán),因此會(huì)丟失最后一段時(shí)間的事務(wù)。
2,當(dāng)操作系統(tǒng)宕機(jī)時(shí),重啟數(shù)據(jù)庫(kù)后會(huì)丟失未從文件系統(tǒng)緩存刷新到重做日志文件那部分事務(wù)。

下圖有助于理解

重做日志塊

在InnoDB存儲(chǔ)引擎中,重做日志都是以512字節(jié)進(jìn)行存儲(chǔ)的。意味著重做日志緩存、重做日志文件都是以塊(block)的方式進(jìn)行保存的,每塊512字節(jié)。

重做日志頭12字節(jié),重做日志尾8字節(jié),故每個(gè)重做日志塊實(shí)際可以存儲(chǔ)492字節(jié)。

重做日志格式

redo log是基于頁(yè)的格式來(lái)記錄的。默認(rèn)情況下,innodb的頁(yè)大小是16KB(由 innodb_page_size變量控制),一個(gè)頁(yè)內(nèi)可以存放非常多的log block(每個(gè)512字節(jié)),而log block中記錄的又是數(shù)據(jù)頁(yè)的變化。

log body的格式分為4部分:

  • redo_log_type:占用1個(gè)字節(jié),表示redo log的日志類(lèi)型。
  • space:表示表空間的ID,采用壓縮的方式后,占用的空間可能小于4字節(jié)。
  • page_no:表示頁(yè)的偏移量,同樣是壓縮過(guò)的。
  • redo_log_body表示每個(gè)重做日志的數(shù)據(jù)部分,恢復(fù)時(shí)會(huì)調(diào)用相應(yīng)的函數(shù)進(jìn)行解析。例如insert語(yǔ)句和delete語(yǔ)句寫(xiě)入redo log的內(nèi)容是不一樣的。

如下圖,分別是insert和delete大致的記錄方式。

redo日志恢復(fù)

下面LSN(Log Sequence Number)代表checkpoint,當(dāng)數(shù)據(jù)庫(kù)在LSN為10000時(shí)發(fā)生宕機(jī),恢復(fù)操作僅恢復(fù)LSN10000-LSN13000范圍內(nèi)日志

undo log

undo log的作用

undo是邏輯日志,只是將數(shù)據(jù)庫(kù)邏輯地恢復(fù)到原來(lái)的樣子;所有修改都被邏輯地取消了,但是數(shù)據(jù)結(jié)構(gòu)和頁(yè)本身在回滾之后可能不大相同。

undo log有兩個(gè)作用:提供回滾和多個(gè)行版本控制(MVCC)。

InnoDB存儲(chǔ)引擎回滾時(shí),對(duì)于每個(gè)INSERT,會(huì)完成一個(gè)DELETE;對(duì)于每個(gè)DELETE,會(huì)執(zhí)行一個(gè)INSERT;對(duì)于每個(gè)UPDATE,會(huì)執(zhí)行一個(gè)相反的UPDATE,將修改前的行放回去。

MVCC: 當(dāng)用戶讀取一行記錄時(shí),若該記錄已經(jīng)被其他事務(wù)占用,當(dāng)前事務(wù)可以通過(guò)undo讀取之前的行版本信息,以此實(shí)現(xiàn)非鎖定讀取。

undo log的存儲(chǔ)方式

innodb存儲(chǔ)引擎對(duì)undo的管理采用段的方式。rollback segment稱(chēng)為回滾段,每個(gè)回滾段中有1024個(gè)undo log segment。

在以前老版本,只支持1個(gè)rollback segment,這樣就只能記錄1024個(gè)undo log segment。后來(lái)MySQL5.5可以支持128個(gè)rollback segment,即支持128*1024個(gè)undo操作,還可以通過(guò)變量 innodb_undo_logs (5.6版本以前該變量是 innodb_rollback_segments )自定義多少個(gè)rollback segment,默認(rèn)值為128。

undo log默認(rèn)存放在共享表空間中。

事務(wù)提交undo log處理過(guò)程

當(dāng)事務(wù)提交時(shí),InnoDB存儲(chǔ)引擎會(huì)做以下兩件事:

  • 將undo log放入一個(gè)列表中,以供之后的purge使用,是否可以最終刪除undo log及所在頁(yè)由purge線程來(lái)判斷
  • 判斷undo log 所在的頁(yè)是否可以重用,若可以,分配給下個(gè)事務(wù)使用

當(dāng)事務(wù)提交時(shí),首先將undo log放入鏈表中,然后判斷undo頁(yè)的使用空間是否小于3/4,若是,則表示該undo頁(yè)可以被重用,之后新的undo log記錄在當(dāng)前undo log的后面

undo log分為:

  • insert undo log
  • update undo log

因?yàn)槭聞?wù)隔離性,insert undo log對(duì)其他事務(wù)不可見(jiàn),所以該undo log可以在事務(wù)提交后直接刪除,不需要進(jìn)行purge操作。

update undo log記錄的是對(duì)delete和update操作產(chǎn)生的undo log。該undo log可能需要提供MVCC機(jī)制,因此不能提交時(shí)就進(jìn)行刪除

update分為兩種情況:

  • date的列如果不是主鍵列,在undo log中直接反向記錄是如何update的。即update是直接進(jìn)行的。
  • update主鍵的操作可以分為兩步:
  • 首先將原主鍵記錄標(biāo)記為已刪除,因此需要產(chǎn)生一個(gè)類(lèi)型為T(mén)RX_UNDO_DEL_MARK_REC的undo log
  • 之后插入一條新的記錄,產(chǎn)生一個(gè)類(lèi)型為T(mén)RX_UNDO_INSERT_MARK_REC的undo log

InnoDB purge時(shí),會(huì)先從history列表找undo log,然后再?gòu)膗ndo page中找undo log;可以避免大量隨機(jī)讀取操作,從而提高purge效率。

MVCC(多版本并發(fā)控制)

MVCC其實(shí)就是在每一行記錄后面增加兩個(gè)隱藏列,記錄創(chuàng)建版本號(hào)和刪除版本號(hào),而每一個(gè)事務(wù)在啟動(dòng)的時(shí)候,都有一個(gè)唯一的遞增的版本號(hào)。

MVCC只在REPEATABLE READ 和READ COMMITTED兩個(gè)隔離級(jí)別下工作。讀未提交不存在版本問(wèn)題,序列化則對(duì)所有讀取行加鎖。

示例:

插入操作:記錄的創(chuàng)建版本號(hào)就是事務(wù)版本號(hào)

如插入一條記錄,事務(wù)id假設(shè)是1,則創(chuàng)建版本號(hào)也是1

id name create version delete version
1 test 1

更新操作:先標(biāo)記舊版本號(hào)為已刪除,版本號(hào)就是當(dāng)前版本號(hào),再插入一條新的記錄

如事務(wù)2把name字段更新
update table set name = 'new test' where id = 1;

原來(lái)的記錄被標(biāo)記刪除,刪除版本號(hào)為2,并插入新記錄,創(chuàng)建版本號(hào)為2

id name create version delete version
1 test 1 2
1 new test 2


刪除操作:把事務(wù)版本作為刪除版本號(hào)

如事務(wù)3把記錄刪除
delete from table where id = 1;

id name create version delete version
1 test 2 3

查詢操作

需滿足以下兩個(gè)條件的記錄才能被事務(wù)查詢出來(lái):

  • InnoDB只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行
  • 行的刪除版本要么未定義,要么大于當(dāng)前版本號(hào),這可以確保事務(wù)讀取到的行,在事務(wù)未開(kāi)始之前未被刪除

MVCC好處:減少鎖的爭(zhēng)用,提升性能

binlog

二進(jìn)制文件概念及作用

二進(jìn)制文件(binary log)記錄了對(duì)MySQL數(shù)據(jù)庫(kù)執(zhí)行更改的所有操作(不包含SELECT、SHOW等,因?yàn)閷?duì)數(shù)據(jù)沒(méi)有修改)

二進(jìn)制文件主要幾種作用:

  • 恢復(fù):某些數(shù)據(jù)的恢復(fù)需要二進(jìn)制日志
  • 復(fù)制: 通過(guò)復(fù)制和執(zhí)行二進(jìn)制日志使一臺(tái)遠(yuǎn)程的MySQL(slave)與另一臺(tái)MySQL數(shù)據(jù)庫(kù)(master)進(jìn)行實(shí)時(shí)同步
  • 審計(jì): 用戶可以通過(guò)二進(jìn)制日志中信息來(lái)進(jìn)行審計(jì),判斷是否有對(duì)數(shù)據(jù)庫(kù)進(jìn)行注入的攻擊

二進(jìn)制文件三個(gè)格式

MySQL 5.1開(kāi)始引入binlog_format參數(shù),該參數(shù)可設(shè)值有STATEMENT、ROW和MIX

  • STATEMENT: 二進(jìn)制文件記錄的是日志的邏輯SQL語(yǔ)句
  • ROW:記錄表的行更改情況。如果設(shè)置了ROW模式,可以將InnoDB事務(wù)隔離級(jí)別設(shè)為READ_COMMITTED,以獲得更好的并發(fā)性
  • MIX:MySQL默認(rèn)采用STATEMENT格式進(jìn)行二進(jìn)制文件的記錄,但在一些情況下會(huì)使用ROW,可能的情況有:
  • 表的存儲(chǔ)引擎為NDB,這時(shí)對(duì)表DML操作都以ROW格式進(jìn)行
  • 使用了UUID()、USER()、CURRENT_USER()、FOUND_ROWS()、ROW_COUNT()等不確定函數(shù)
  • 使用了INSERT DELAY語(yǔ)句
  • 使用了用戶定義函數(shù)
  • 使用了臨時(shí)表

redo log和二進(jìn)制文件區(qū)別

(二進(jìn)制文件用來(lái)進(jìn)行POINT-IN-TIME(PIT))的恢復(fù)及主從復(fù)制環(huán)境的建立。

  • 二進(jìn)制文件會(huì)記錄所有與MySQL數(shù)據(jù)庫(kù)有關(guān)的日志記錄,包括InnoDB、MyISAM等其他存儲(chǔ)引擎的日志。而InnoDB存儲(chǔ)引擎的重做日志只記錄有關(guān)該存儲(chǔ)引擎本身的事務(wù)日志。
  • 記錄的內(nèi)容不同,無(wú)論用戶將二進(jìn)制日志文件記錄的格式設(shè)為STATEMENT、ROW或MIXED,其記錄的都是關(guān)于一個(gè)事務(wù)的具體操作內(nèi)容,即該日志是邏輯日志。而InnoDB存儲(chǔ)引擎的重做日志文件記錄的是關(guān)于每個(gè)頁(yè)的更改的物理情況。
  • 此外,寫(xiě)入的時(shí)間頁(yè)不同,二進(jìn)制日志文件僅再事務(wù)提交前進(jìn)行提交,即只寫(xiě)磁盤(pán)一次,不論這時(shí)該事務(wù)多大。而在事務(wù)進(jìn)行的過(guò)程中,卻不斷有重做日志條目(reod entry)被寫(xiě)入到重做日志文件中。

group commit

若事務(wù)為非只讀事務(wù),則每次事務(wù)提交時(shí)需要進(jìn)行一次fsync操作,以此保證重做日志都已經(jīng)寫(xiě)入磁盤(pán)。但磁盤(pán)fsync性能有限,為提高磁盤(pán)fsync效率,當(dāng)前數(shù)據(jù)庫(kù)都提供group commit功能,即一次可以刷新確保多個(gè)事務(wù)日志被寫(xiě)入文件。

對(duì)InnoDB group commit,進(jìn)行兩階段操作:

  • 修改內(nèi)存中事務(wù)對(duì)應(yīng)的信息,并且將日志寫(xiě)入重做日志緩沖
  • 調(diào)用fsync將確保日志都從重做日志緩沖寫(xiě)入磁盤(pán)

InnoDB1.2前,開(kāi)啟二進(jìn)制文件,group commit功能失效問(wèn)題:

開(kāi)啟二進(jìn)制文件后,其步驟如下:
1)當(dāng)事務(wù)提交時(shí),InnoDB存儲(chǔ)引擎進(jìn)行prepare操作
2)MySQL數(shù)據(jù)庫(kù)上層寫(xiě)入二進(jìn)制文件
3)InnoDB將日志寫(xiě)入重做日志文件

a)修改內(nèi)存中事務(wù)對(duì)應(yīng)的信息,并將日志寫(xiě)入重做日志緩沖b)調(diào)用fsync將確保日志都從重做日志緩沖寫(xiě)入磁盤(pán)

其中在保證MySQL數(shù)據(jù)庫(kù)上層二進(jìn)制文件的寫(xiě)入順序,和InnoDB事務(wù)提交順序一致,MySQL內(nèi)部使用了prepare_commit_mutex鎖,從而步驟3)中a)步不可以在其他事務(wù)執(zhí)行步驟b)時(shí)進(jìn)行,從而導(dǎo)致roup commit功能失效。

解決方案便是BLGC(Binary Log Group Commit)

MySQL 5.6 BLGC實(shí)現(xiàn)方式分為三個(gè)階段:

  • Flush階段:將每個(gè)事務(wù)的二進(jìn)制文件寫(xiě)入內(nèi)存
  • Sync階段:將內(nèi)存中的二進(jìn)制刷新到磁盤(pán),若隊(duì)列有多個(gè)事務(wù),那么僅一次fsync操作就完成了二進(jìn)制日志的寫(xiě)入,這就是BLGC
  • Commit階段:leader根據(jù)順序調(diào)用存儲(chǔ)引擎層事務(wù)提交,由于innodb本就支持group commit,所以解決了因?yàn)殒i prepare_commit_mutex 而導(dǎo)致的group commit失效問(wèn)題。

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

相關(guān)文章

  • MySQL中INSERT+SELECT的使用方式

    MySQL中INSERT+SELECT的使用方式

    MySQL的INSERT INTO SELECT FROM語(yǔ)句允許用戶通過(guò)一條SQL語(yǔ)句實(shí)現(xiàn)從一個(gè)或多個(gè)表中查詢數(shù)據(jù)并將結(jié)果插入到另一個(gè)表中,這種方式特別適用于需要將數(shù)據(jù)從一張表遷移到另一張表,或者基于多表查詢結(jié)果創(chuàng)建新表的場(chǎng)景
    2024-10-10
  • MAC下Mysql5.7.10版本修改root密碼的方法

    MAC下Mysql5.7.10版本修改root密碼的方法

    這篇文章主要介紹了MAC下Mysql5.7.10版本修改root密碼的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-03-03
  • Mac下MySQL初始化密碼操作

    Mac下MySQL初始化密碼操作

    個(gè)人在Mac上操作數(shù)據(jù)庫(kù),遇到的啟動(dòng)數(shù)據(jù)庫(kù)問(wèn)題的簡(jiǎn)單記錄。接下來(lái)通過(guò)本文給大家介紹Mac下MySQL初始化密碼操作,需要的朋友參考下
    2017-03-03
  • 詳解如何修改MySQL最大連接數(shù)

    詳解如何修改MySQL最大連接數(shù)

    本文主要介紹了詳解如何修改MySQL最大連接數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • MySQL rand函數(shù)實(shí)現(xiàn)隨機(jī)數(shù)的方法

    MySQL rand函數(shù)實(shí)現(xiàn)隨機(jī)數(shù)的方法

    在mysql中,使用隨機(jī)數(shù)寫(xiě)一個(gè)語(yǔ)句能一下更新幾百條MYSQL數(shù)據(jù)嗎?答案是肯定的,使用MySQL rand函數(shù),就可以使現(xiàn)在隨機(jī)數(shù)
    2016-09-09
  • mySQL 8.0.33安裝指南(推薦)

    mySQL 8.0.33安裝指南(推薦)

    本文提供MySQL8.0.33的詳細(xì)安裝步驟,從解壓安裝包到設(shè)置系統(tǒng)服務(wù)、配置遠(yuǎn)程訪問(wèn)及安全設(shè)置等,包括創(chuàng)建和配置MySQL用戶,設(shè)置環(huán)境變量,初始化數(shù)據(jù)庫(kù)等關(guān)鍵操作,同時(shí)強(qiáng)調(diào)安全性的重要性,如設(shè)置強(qiáng)密碼、限制遠(yuǎn)程訪問(wèn)權(quán)限,并建議在重要操作前進(jìn)行數(shù)據(jù)庫(kù)備份
    2024-10-10
  • Mac下忘記mysql密碼重新設(shè)置密碼的圖文教程

    Mac下忘記mysql密碼重新設(shè)置密碼的圖文教程

    這篇文章主要介紹了Mac下忘記mysql密碼重新設(shè)置密碼的教程,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12
  • MySQL因大事務(wù)導(dǎo)致的Insert慢實(shí)例分析

    MySQL因大事務(wù)導(dǎo)致的Insert慢實(shí)例分析

    這篇文章主要給大家介紹了關(guān)于MySQL因大事務(wù)導(dǎo)致Insert慢的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • MySQL中使用SQL語(yǔ)句對(duì)字段進(jìn)行重命名

    MySQL中使用SQL語(yǔ)句對(duì)字段進(jìn)行重命名

    MySQL中,如何使用SQL語(yǔ)句來(lái)對(duì)表中某一個(gè)字段進(jìn)行重命名呢?我們將使用alter table 這一SQL語(yǔ)句,需要的朋友可以參考下
    2016-04-04
  • mysql的XA事務(wù)恢復(fù)過(guò)程詳解

    mysql的XA事務(wù)恢復(fù)過(guò)程詳解

    XA事務(wù)支持限于InnoDB存儲(chǔ)引擎,本文將詳細(xì)介紹mysql的XA事務(wù)恢復(fù)過(guò)程
    2012-11-11

最新評(píng)論