真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

一文搞懂MySQL之redo日志(含字節(jié)面試題)-創(chuàng)新互聯(lián)

MySQL之redo日志 前言

前幾天看到一道面試題,題目是:事務(wù)還沒提交的時候,redo log 能不能被持久化到磁盤呢?

“只有客戶發(fā)展了,才有我們的生存與發(fā)展!”這是創(chuàng)新互聯(lián)的服務(wù)宗旨!把網(wǎng)站當作互聯(lián)網(wǎng)產(chǎn)品,產(chǎn)品思維更注重全局思維、需求分析和迭代思維,在網(wǎng)站建設(shè)中就是為了建設(shè)一個不僅審美在線,而且實用性極高的網(wǎng)站。創(chuàng)新互聯(lián)對成都網(wǎng)站設(shè)計、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站開發(fā)、網(wǎng)頁設(shè)計、網(wǎng)站優(yōu)化、網(wǎng)絡(luò)推廣、探索永無止境。

在學習和了解redo日志前,我就在想,這題目啥玩意???一個開發(fā)崗都考這么細嗎?

后來,學習完redo日志后,發(fā)現(xiàn)這個面試題確實挺有意思的。就是考查你對redo日志的了解到底有多深,是停留在表面的理解呢?還是真的修煉到一定程度了,這個題目真的就可以反映出來。

所以,你的答案是什么呢?(答案在文末)

相信讀完本篇文章,理解redo日志后,就會有你自己的答案了…

1. 什么是日志?

按照普通字面意思來理解的話,日志是日記中的一種,多指非個人的,一般是記載每天所做的工作。書面日志如"教學日志",“班級日志”,"工作日志"等…

而我們這里所指的日志,則是程序中的日志。對程序的運行過程進行詳細的記錄;是為了保障系統(tǒng)的正常運行,是在程序出現(xiàn)問題時,方便程序員去查閱日志發(fā)現(xiàn)錯誤的重要手段之一。

1.1 數(shù)據(jù)庫日志

在數(shù)據(jù)庫系統(tǒng)中,對數(shù)據(jù)的任何更新操作(如:增加、修改、刪除),都要把相關(guān)操作的命令、執(zhí)行時間、數(shù)據(jù)的更新等信息保存下來。這些被保存的信息就是數(shù)據(jù)庫日志。也就是說,數(shù)據(jù)庫日志是數(shù)據(jù)庫系統(tǒng)中所有更新活動的操作序列。

更為重要的是,數(shù)據(jù)庫日志是系統(tǒng)正常運行、保持數(shù)據(jù)一致性的重要手段。

redo log(重做日志)則是數(shù)據(jù)庫日志中的一種。它支持再寫入,恢復(fù)提交事務(wù)修改的數(shù)據(jù)頁操作,以此來保證數(shù)據(jù)的持久性。

2. 為什么需要redo日志?

眾所周知,事務(wù)有四種特性:原子性、一致性、隔離性、持久性。

那么事務(wù)的四種特性到底是基于什么機制實現(xiàn)的呢?

  • 事務(wù)的隔離性由鎖機制實現(xiàn)
  • 事務(wù)的原子性、一致性、持久性由事務(wù)的redo日志和undo日志來保證。

InnoDB存儲引擎是以頁為單位來管理存儲空間的。在真正訪問頁面之前需要把在磁盤上的頁緩存到內(nèi)存中的Buffer Pool之后才可以訪問。所有的變更都必須先更新緩沖池中的數(shù)據(jù),然后緩沖池中的臟頁會以一定的頻率被刷入磁盤(checkPoint機制),通過緩沖池來優(yōu)化CPU和磁盤之間的鴻溝,這樣就可以保證整體的性能不會下降太快。

但是,由于checkPoint機制并不是在每次修改數(shù)據(jù)時就將臟頁刷入磁盤,這個時候,就怕數(shù)據(jù)庫宕機,一旦宕機,那么緩沖池中的所有臟頁都會被清除;就會出現(xiàn),我們commit親自提交的事務(wù),數(shù)據(jù)庫竟然沒有改變(表情:大驚失色)!

也就是說,事務(wù)的持久性失效了??!

那么如何保證事務(wù)的持久性呢?這個時候,redo log就應(yīng)運而生了。

2.1 redo log 的作用

我們只是想讓已經(jīng)提交的事務(wù)對數(shù)據(jù)庫中數(shù)據(jù)所做的修改永久生效,即使系統(tǒng)崩潰,在重啟后也能把修改的數(shù)據(jù)寫入數(shù)據(jù)庫中。我們只需要將修改了哪些數(shù)據(jù)記錄一下就好。比如:某個事務(wù)將系統(tǒng)表空間中第10號頁面中地址偏移量為100處那個字節(jié)的值1改為2;則只需要記錄:將第0號表空間的10號頁面的地址偏移量為100處的值更新為 2 。

InnoDB引擎的事務(wù)采用了WAL技術(shù)(Write-Ahead Logging 預(yù)寫日志系統(tǒng)),這種技術(shù)的思想就是先寫日志,再寫磁盤,只有日志寫入成功,才算事務(wù)提交成功,這里的日志就是redo log。當發(fā)生宕機且數(shù)據(jù)未刷到磁盤的時候,可以通過redo log來恢復(fù),保證ACID中的D,這就是redo log的作用。

在這里插入圖片描述

3. redo日志的好處、特點 3.1 好處
  • redo日志降低了刷盤頻率。若沒有redo日志,數(shù)據(jù)庫系統(tǒng)則必須確保每次事務(wù)對數(shù)據(jù)庫進行修改時,必須馬上同步到磁盤(不管修改數(shù)據(jù)量的多少)
  • redo日志占用的空間非常小。它只保存沒有刷新到磁盤上的操作內(nèi)容。
3.2 特點
  • redo日志是順序?qū)懭氪疟P的。在執(zhí)行事務(wù)的過程中,每執(zhí)行一條語句,就可能產(chǎn)生若干條redo日志,這些日志是按照產(chǎn)生的順序?qū)懭氪疟P的,也就是使用順序IO,效率比隨機IO快。
  • 事務(wù)執(zhí)行過程中,redo log不斷記錄。
4. redo的組成

redo log可以簡單分為以下兩個部分:重做日志的緩沖、重做日志文件。

4.1 重做日志的緩沖 (redo log buffer)

在服務(wù)器啟動時就向操作系統(tǒng)申請了一大片稱之為redo log buffer的連續(xù)內(nèi)存空間,翻譯成中文就是redo日志緩沖區(qū)。這片內(nèi)存空間被劃分成若干個連續(xù)的redo log block。一個redo log block占用512字節(jié)大小。redo log buffer是屬于內(nèi)存層面,是易丟失的。

在這里插入圖片描述

參數(shù)設(shè)置:innodb_log_buffer_size

redo log buffer 大小,默認16M,大值是4096M,最小值為1M。

mysql>show variables like '%innodb_log_buffer_size%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
4.2 重做日志文件(redo log file)

redo log file是保存在硬盤中,是持久化的。

在這里插入圖片描述

4.2 redo log的流轉(zhuǎn)過程

以一個更新事務(wù)為例,redo log 流轉(zhuǎn)過程,如下圖所示:

在這里插入圖片描述

  • 第1步:先將原始數(shù)據(jù)從磁盤中讀入內(nèi)存中(數(shù)據(jù)庫緩沖池)

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

  • 第3步:當事務(wù)commit時,將redo log buffer中的內(nèi)容刷新到 redo log file,對 redo log file采用追加寫的方式

  • 第4步:定期將內(nèi)存中修改的數(shù)據(jù)刷新到磁盤中

5.*redo log 的刷盤策略

redo log的寫入并不是直接將數(shù)據(jù)寫入磁盤的,InnoDB引擎會在寫redo log的時候先寫將數(shù)據(jù)寫入redo log buffer,之后以一定的頻率刷入到真正的redo log file中。這里的一定頻率怎么看待呢?這就是我們要說的刷盤策略。

在這里插入圖片描述

注意:redo log buffer刷盤到redo log file的過程并不是真正的刷到磁盤中去,只是刷入到文件系統(tǒng)緩存(page cache)中去(這是現(xiàn)代操作系統(tǒng)為了提高文件寫入效率做的一個優(yōu)化),真正的寫入會交給系統(tǒng)自己來決定(比如page cache足夠大了時)。

那么對于InnoDB來說就存在一個問題,如果交給系統(tǒng)來進行寫入,同樣如果系統(tǒng)宕機,那么數(shù)據(jù)也丟失了(雖然整個系統(tǒng)宕機的概率還是比較小的)。

針對這種情況,InnoDB給出innodb_flush_log_at_trx_commit參數(shù),該參數(shù)控制 commit 提交事務(wù)時,如何將 redo log buffer 中的日志刷新到 redo log file 中。它支持三種策略:

  • 值為0時:表示每次事務(wù)提交時不進行刷盤操作,都只是把 redo log 留在 redo log buffer 中。(系統(tǒng)默認master thread每隔1s進行一次重做日志的同步)
  • 值為1時:每次事務(wù)提交的時候,都執(zhí)行 fsync (同步) 將 redo log 直接持久化到磁盤( 默認值 )
  • 值為2時:每次事務(wù)提交的時候,都只執(zhí)行 write(寫) 將 redo log 寫到文件系統(tǒng)的 page cache 中。由OS自己決定什么時候fsync(同步)到磁盤文件(redo log file)。
show variables like 'innodb_flush_log_at_trx_commit';

mysql>show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.00 sec)

另外,InnoDB存儲引擎有一個后臺線程(master thread),每隔1秒,就會把redo log buffer中的內(nèi)容寫到文件系統(tǒng)緩存(page cache),然后調(diào)用刷盤操作。

在這里插入圖片描述

也就是說,一個沒有提交事務(wù)的redo log記錄,也可能會被刷入磁盤。因為在事務(wù)執(zhí)行過程中,只要發(fā)生數(shù)據(jù)的更改,redo log記錄是會馬上寫入到redo log buffer中,這些redo log記錄會被后臺線程刷盤。所以說,對于上面那個字節(jié)的面試題來說。

相信你們已經(jīng)有答案了。

除了后臺線程每秒1次的輪詢操作,還有一種情況,當redo log buffer占用的空間即將達到innodb_log_buffer_size(這個參數(shù)默認是16M)的一半的時候,也就是redo log buffer的容量達到8M時,后臺線程會主動寫盤(由于這個事務(wù)可能并沒有提交,所以這個寫盤動作只是 write 到了文件系統(tǒng)的 page cache,仍然是在內(nèi)存中,并沒有調(diào)用 fsync 真正落盤)。

6. 重寫日志文件(redo log file) 6.1 相關(guān)參數(shù)設(shè)置
  • innodb_log_group_home_dir:指定redo log文件所在的路徑,默認值為./。表示在數(shù)據(jù)庫的數(shù)據(jù)目錄下。

    MySQL的默認數(shù)據(jù)目錄(linux):var/lib/mysql;window下則是C:\ProgramData\MySQL\MySQL Server 8.0\Data,文件下有兩個名為ib_logfile0ib_logfile1的文件。redo log buffer中的日志默認情況下就是刷新到這兩個磁盤文件中。

  • innodb_log_files_in_group:指明redo log file的個數(shù),命名方式如:ib_logfile0,ib_logfile1…ib_logfilen。默認2個,大100個。

    mysql>show variables like 'innodb_log_files_in_group';
    +---------------------------+-------+
    | Variable_name | Value |
    +---------------------------+-------+
    | innodb_log_files_in_group | 2 |
    +---------------------------+-------+
  • innodb_flush_log_at_trx_commit:控制 redo log 刷新到磁盤的策略,默認為1(前面已經(jīng)介紹過)。

  • innodb_log_file_size:單個 redo log file文件設(shè)置大小,默認值為48M。大值為512G,注意大值指的是整個 redo log file系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size )不能大于大值512G。

    mysql>show variables like 'innodb_log_file_size';
    +----------------------+----------+
    | Variable_name | Value |
    +----------------------+----------+
    | innodb_log_file_size | 50331648 |
    +----------------------+----------+
6.2 日志文件組

從上邊的描述中可以看到,磁盤上的redo日志文件不只一個,而是可以以一個日志文件組的形式出現(xiàn)的。這些文件以ib_logfile[數(shù)字]數(shù)字可以是0、1、2…)的形式進行命名,每個的redo日志文件大小都是一樣的。

在將redo日志寫入日志文件組時,是從ib_logfile0開始寫,如果ib_logfile0寫滿了,就接著ib_logfile1寫。同理,ib_logfile1寫滿了就去寫ib_logfile2,依此類推。如果寫到最后一個文件該咋辦?那就重新轉(zhuǎn)到ib_logfile0繼續(xù)寫,所以整個過程如下圖所示:

在這里插入圖片描述

總共的redo log file的大小其實就是:innodb_log_file_size × innodb_log_files_in_group(即單個文件大小 * 文件個數(shù))。

有人可能會問,ib_logfile0都已經(jīng)寫完了,怎么最后還可以重新轉(zhuǎn)到ib_logfile0繼續(xù)寫呢?那不就把之前的數(shù)據(jù)給覆蓋了嗎?

對于這個問題,InnoDB的設(shè)計者早就想到了,并提出了checkPoint的概念。

6.2.1 checkpoint機制

在整個日志文件組中還有兩個重要的屬性,分別是write pos、checkpoint。

  • write pos是當前記錄的位置,也就是當前使用到的位置,一邊寫一邊后移
  • checkpoint是當前要擦除的位置,也是往后推移

每次刷盤redo log記錄到日志文件組中,write pos位置就會從0開始后移更新。每次MySQL通過加載日志文件組恢復(fù)數(shù)據(jù)時(也就是通過redo log恢復(fù)數(shù)據(jù)庫的數(shù)據(jù)),則會清空加載過的redo log記錄(已經(jīng)恢復(fù)的數(shù)據(jù)),并把 checkpoint后移更新。write pos和checkpoint之間的還空著的部分可以用來寫入新的redo log記錄。

在這里插入圖片描述

如果 write pos 追上 checkpoint ,表示日志文件組滿了,這時候不能再寫入新的 redo log記錄,MySQL 得停下來,清空一些記錄,把 checkpoint 推進一下。

在這里插入圖片描述

7. 總結(jié)

本文講解了redo日志的出現(xiàn)解決了事務(wù)的持久性的問題;以及redo日志的好處和它的特點,還分析了redo日志的組成:redo log buffer 和redo log file,并且介紹了它們各自的職責以及相應(yīng)的作用。

還有比較重要的一點:redo日志的刷盤策略,這對我們之后的數(shù)據(jù)庫調(diào)優(yōu)有一定的幫助和經(jīng)驗。

以及最后redo日志在文件中到底是如何存儲的,它的格式、它的運行機制等。

InnoDB的更新操作采用的是Write Ahead Log(預(yù)先日志持久化)策略,即先寫日志,再寫入磁盤。重點掌握redo的作用、組成和刷盤策略等。

在這里插入圖片描述

面試答案:

答案是:事務(wù)還沒有提交的時候,redo log 是有可能被持久化到磁盤的。

redolog 的具體落盤操作是這樣的:在事務(wù)運行的過程中,MySQL 會先把日志寫到 redolog buffer 中,等到事務(wù)真正提交的時候,再統(tǒng)一把 redolog buffer 中的數(shù)據(jù)寫到 redo log 文件中。不過這個從 redolog buffer 寫到 redo log 文件中的操作也就是 write 并不就是落盤操作了,這里僅僅是把 redolog 寫到了文件系統(tǒng)的 page cache 上,最后還需要執(zhí)行 fsync (同步)才能夠?qū)崿F(xiàn)真正的落盤。

InnoDB 有一個后臺線程,每隔 1 秒輪詢一次,具體的操作是這樣的:調(diào)用 write 將 redolog buffer 中的日志寫到文件系統(tǒng)的 page cache,然后調(diào)用 fsync 持久化到磁盤。而在事務(wù)執(zhí)行中間過程的 redo log 都是直接寫在 redolog buffer 中的,也就是說,一個沒有提交的事務(wù)的 redo log,也是有可能會被后臺線程一起持久化到磁盤的。

另外,除了后臺線程每秒一次的輪詢操作外,還有兩種場景會讓一個沒有提交的事務(wù)的 redo log 寫盤:

innodb_flush_log_at_trx_commit 設(shè)置是 1,這樣并行的某個事務(wù)提交的時候,就會順帶將這個事務(wù)的 redolog buffer 持久化到磁盤

舉個例子,假設(shè)事務(wù) A 執(zhí)行到一半,已經(jīng)寫了一些 redo log 到 redo log buffer 中,這時候有另外一個事務(wù) B 提交,按照 innodb_flush_log_at_trx_commit = 1 的邏輯,事務(wù) B 要把 redolog buffer 里的日志全部持久化到磁盤,這時候,就會帶上事務(wù) A 在 redolog buffer 里的日志一起持久化到磁盤

redo log buffer 占用的空間達到 redo log buffer 大?。ㄓ蓞?shù) innodb_log_buffer_size 控制,默認是 48MB)一半的時候,后臺線程會主動寫盤。不過由于這個事務(wù)并沒有提交,所以這個寫盤動作只是 write 到了文件系統(tǒng)的 page cache,仍然是在內(nèi)存中,并沒有調(diào)用 fsync 真正落盤。

具體參考:https://zhuanlan.zhihu.com/p/456411101


寫在最后

好了,以上就是本篇文章的全部內(nèi)容,如果對你有所收獲或者啟發(fā)。希望能點贊+收藏支持一下!

我是胡亦,一名熱愛分享技術(shù)干貨的博主。

我們下次再見!!🙋?♂?🙋?♂?

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)頁名稱:一文搞懂MySQL之redo日志(含字節(jié)面試題)-創(chuàng)新互聯(lián)
轉(zhuǎn)載來于:http://weahome.cn/article/iejgg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部