久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL的binlog、redo log和undo log怎么使用

139次閱讀
沒有評論

共計 6691 個字符,預計需要花費 17 分鐘才能閱讀完成。

這篇文章主要介紹“MySQL 的 binlog、redo log 和 undo log 怎么使用”,在日常操作中,相信很多人在 MySQL 的 binlog、redo log 和 undo log 怎么使用問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”MySQL 的 binlog、redo log 和 undo log 怎么使用”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!

1、binlog

binlog 用于記錄數據庫執行的寫入性操作 (不包括查詢) 信息,以二進制的形式保存在磁盤中。binlog 是 mysql 的邏輯日志,并且由 Server 層進行記錄,使用任何存儲引擎的 mysql 數據庫都會記錄 binlog 日志。

邏輯日志:可以簡單得理解為 sql 語句;

物理日志:MySQL 中數據都是保存在數據頁中的,物理日志記錄的是數據頁上的變更;在這里插入代碼片

binlog 是通過追加的方式進行寫入的,可以通過 max_binlog_size 參數設置每個 binlog 文件的大小,當文件大小達到給定值之后,會生成新的文件來保存日志。

binlog 使用場景
項目 在實際應用中,binlog 的主要使用場景有兩個,分別是主從復制和數據恢復。

主從復制:在 Master 端開啟 binlog,然后將 binlog 發送到各個 Slave 端,Slave 端重放 binlog 從而達到主從數據一致。

數據恢復:通過使用 mysqlbinlog 工具來恢復數據。

MySQL 主從同步原理

主節點 binlog dump 線程
當從節點連接主節點時,主節點會創建一個 log dump 線程,用于發送 binlog 的內容。在讀取 binlog 中的操作時,此線程會對主節點上的 binlog 加鎖,當讀取完成,甚至在發動給從節點之前,鎖會被釋放;

從節點 I / O 線程
當從節點上執行 start slave 命令之后,從節點會創建一個 I / O 線程用來連接主節點,請求主庫中更新的 binlog。I/ O 線程接收到主節點 binlog dump 進程發來的更新之后,保存在本地 relaylog 中;

從節點 SQL 線程
SQL 線程負責讀取 relaylog 中的內容,解析成具體的操作并執行,最終保證主從數據的一致性;
MySQL 數據庫主從同步原理

binlog 的內容
上面說了,binlog 是一種邏輯日志,可以簡單得理解為 sql 語句,但是實際上還包含著執行的 sql 語句的反向邏輯。delete 對應著 delete 本身以及反向的 insert 信息;update 包含著對應的 update 執行前后數據行的相關信息;insert 包含自身的 insert 以及對應的 delete 信息。

binlog 的格式
binlog 共有三種格式,分別是 statement、row 以及 mixed。MySQL 5.7.7 版本之前默認使用的是 statement,MySQL 5.7.7 之后默認使用的是 row。日志的格式可以通過 my.ini 配置文件中的 binlog-format 來修改。
(1)statement:基于 sql 語句的復制(statement-based replication,SBR),每一條修改數據的 sql 語句都會記錄到 binlog 中。

優點:不需要具體記錄某一行的變化,節約空間,減少 io,提高性能;

缺點:在執行 sysdate()或者 sleep()等操作的時候,可能導致主從數據不一致的情況;

(2)row:基于行記錄的復制(row-based replication,RBR),不記錄 sql 語句上下文相關信息,而是記錄哪條記錄被修改的細節。

優點:非常詳細地記錄每一行記錄修改的細節,因而不會出現數據無法被正確復制的情況;

缺點:由于會非常詳細地記錄每一條記錄修改的細節,這樣會產生大量的日志內容。假設現在有一條 update 語句,修改了很多條記錄,則每條修改記錄都會記錄到 binlog 中。特別地,alter table 這個操作,由于表結構的變化,每行記錄都會發生變化,導致日志量暴增;

(3)mixed:根據上面所說的,statement 和 row 各有優缺點,因此出現了 mixed 這個版本,將這二者進行混合。一般情況下使用 statement 格式來進行保存,當遇到 statement 無法解決時,切換為 row 格式來進行保存。
特別地,上面說了,新版本(MySQL 5.7.7 之后)默認使用的 row 格式,這里的 row 也做了相應的優化,在遇到 alter table 這個操作時采用 statement 格式進行記錄,其余操作仍然使用 row 格式。

binlog 刷盤時機

對于 InnoDB 存儲引擎來說,只有在事務提交的時候才會記錄 binlog,此時記錄還在內存中,MySQL 通過 sync_binlog 來控制 binlog 的刷盤時機,取值范圍為 0 -N:

0:不強制刷到磁盤,由系統自行判斷何時寫入磁盤中;

1:每次提交后都要將 binlog 寫入磁盤中;

N:每 N 個事務,才會將 binlog 寫入磁盤中;

從上面可以看出,sync_binlog 最安全的是設置是 1,這也是 MySQL 5.7.7 之后版本的默認值。但是設置一個大一些的值可以提升數據庫性能,因此實際情況下也可以將值適當調大,犧牲一定的一致性來獲取更好的性能。

binlog 的物理文件大小

在 my.ini 配置文件中,可以通過 max_binlog_size 來配置 binlog 的大小。當日志量超過 binlog 文件的大小時,系統會重新生成一個新的文件來繼續保存文件。當一個事務比較大時,或者是當日志越來越多的時候,此時占據的物理空間太大怎么辦?MySQL 提供了一種自動刪除的機制,還是在 my.ini 配置文件中,可以通過配置 expire_logs_days 這個參數來解決,單位為天。當這個參數為 0,表示永不刪除;為 N 時,表示第 N 天后自動刪除。

2、redo log

redolog 是 InnoDB 引擎專有的日志系統。主要是用來實現事務的持久性以及實現 crash-safe 功能。redolog 屬于物理日志,記錄的是 sql 語句執行之后數據頁上的具體修改內容。
我們都知道,當 MySQL 運行的時候,會將數據從磁盤中加載到內存當中。當執行 sql 語句對數據進行修改時,修改后的內容其實都只是暫時保存到內存當中,如果此時斷電或者出現其他情況,這些修改就會丟失。因而,當修改完數據之后,MySQL 會尋找機會將這些內存中的記錄刷回到磁盤當中。但這就出現一個性能問題,主要有兩個方面:

InnoDB 中是以頁為數據單位與磁盤進行交互的,而一個事務很可能只是修改了一個頁上的幾個字節,如果將一個完整的數據頁刷回磁盤當中,浪費資源;

一個事務可能涉及到多個數據頁,這些數據頁只是邏輯上連續,在物理上并不連續,使用隨機 IO 性能太差;

因此,MySQL 設計了 redolog 來記錄事務對數據頁具體做了哪些修改,之后將 redolog 再刷回磁盤當中。你可能會有疑惑,本來就是想減少 io,這不又加上一次 io 么?InnoDB 的設計者在設計之初就已經考慮到了這些。redolog 文件一般都比較小,且在刷回磁盤的過程中是順序 io,相比于隨機 io 來說,性能更好。

redo log 基本概念
redolog 由兩部分組成,一個是內存中的日志緩存 redo log buffer,一個是磁盤中的日志文件 redo log file。當每次對數據記錄進行修改的時候,都會將這些修改內容先寫入 redo log buffer 中,后續等待合適的時機將內存中的修改刷回到 redo log file 中。這種先寫日志,再寫磁盤的技術就是 WAL(Write-Ahead Logging) 技術。需要注意的是 redolog 比數據頁先刷回磁盤,聚簇索引,二級索引,undo 頁面的修改,均需要記錄 redolog。

在計算機操作系統中,用戶空間 (user space) 下的緩沖區數據一般情況下是無法直接寫入磁盤的,中間必須經過操作系統內核空間 (kernel space) 緩沖區 (OS Buffer)。因此,redo log buffer 寫入 redo log file 實際上是先寫入 OS Buffer,然后再通過系統調用 fsync() 將其刷到 redo log file 中,過程如下:

mysql 支持三種將 redo log buffer 寫入 redo log file 的時機,可以通過 innodb_flush_log_at_trx_commit 參數配置,各參數值含義如下:

參數值含義 0(延遲寫)事務提交時不會將 redo log buffer 中日志寫入到 os buffer,而是每秒寫入 os buffer 并調用 fsync()寫入到 redo log file 中。也就是說設置為 0 時是 (大約) 每秒刷新寫入到磁盤中的,當系統崩潰,會丟失 1 秒鐘的數據。1(實時寫,實時刷)事務每次提交都會將 redo log buffer 中的日志寫入 os buffer 并調用 fsync()刷到 redo log file 中。這種方式即使系統崩潰也不會丟失任何數據,但是因為每次提交都寫入磁盤,IO 的性能較差。2(實時寫,延遲刷)每次提交都僅寫入到 os buffer,然后是每秒調用 fsync()將 os buffer 中的日志寫入到 redo log file。

redo log 記錄形式
redolog 采用固定大小,循環寫入的格式,當 redolog 寫滿之后,會重新從頭開始寫。為什么這么設計呢?
redo log 存在的意義主要就是降低對數據頁刷盤的要求。redolog 記錄了數據頁上的修改,但是當數據頁也刷回到磁盤后,這些記錄就失去作用了。因此當 MySQL 判斷之前的 redolog 已經失去作用之后,新數據會將這些失效的數據進行覆蓋。那如何判斷該不該進行覆蓋呢?

上圖是 redo log file 的示意圖,write pos 表示 redolog 當前記錄的日志序列號 LSN(log sequence number)。當數據頁也已經刷回磁盤之后,會更新 redo log file 中的 LSN,表示到這個 LSN 之前的數據已經落盤,這個 LSN 就是 check point。write pos 到 check point 之間的部分是 redolog 空余的部分,用于記錄新的記錄;check point 到 write pos 之間是 redolog 已經記錄的數據頁修改部分,但此時數據頁還未刷回磁盤的部分。當 write pos 追上 check point 時,會先推動 check point 向前移動,空出位置再記錄新的日志。

啟動 innodb 的時候,不管上次是正常關閉還是異常關閉,總是會進行恢復操作。恢復時,會先檢查數據頁中的 LSN,如果這個 LSN 小于 redolog 中的 LSN,即 write pos 位置,說明在 redolog 上記錄著數據頁上尚未完成的操作,接著就會從最近的一個 check point 出發,開始同步數據。

那有沒有可能數據頁中的 LSN 大于 redolog 中的 LSN 呢?答案是當然可能。出現這種情況時,這時超出 redolog 的部分將不會重做,因為這本身就表示已經做過的事情,無需再重做。
redo log 與 binlog 區別

redo logbinlog 文件大小 redo log 的大小是固定的。binlog 可通過配置參數 max_binlog_size 設置每個 binlog 文件的大小。實現方式 redo log 是 InnoDB 引擎層實現的,并不是所有引擎都有。binlog 是 Server 層實現的,所有引擎都可以使用 binlog 日志記錄方式 redo log 采用循環寫的方式記錄,當寫到結尾時,會回到開頭循環寫日志。binlog 通過追加的方式記錄,當文件大小大于給定值后,后續的日志會記錄到新的文件上適用場景 redo log 適用于崩潰恢復(crash-safe)binlog 適用于主從復制和數據恢復

由 binlog 和 redo log 的區別可知:binlog 日志只用于歸檔,只依靠 binlog 是沒有 crash-safe 能力的。但只有 redo log 也不行,因為 redo log 是 InnoDB 特有的,且日志上的記錄落盤后會被覆蓋掉。因此需要 binlog 和 redo log 二者同時記錄,才能保證當數據庫發生宕機重啟時,數據不會丟失。
兩階段提交
上面簡單介紹了 redolog 和 binlog,在對數據進行修改時,他們都會對這些修改進行保存落地,只是一個是物理日志,一個是邏輯日志。那他倆具體在修改過程中是如何執行的呢?

假設現在有一條 update 語句要執行,update from table_name set c=c+1 where id=2,執行流程如下:

先定位到 id= 2 這一條記錄;

執行器拿到引擎給的行數據,把這個值加上 1,得到新的一行數據,再調用引擎接口寫入這行新數據;

引擎將這行新數據更新到內存中,同時將這個更新操作記錄到 redolog 里面,此時 redolog 處于 prepare 狀態。然后告知執行器執行完成了,隨時可以提交事務;

執行器生成這個操作的 binlog,并把 binlog 寫入磁盤;

執行器調用引擎的提交事務接口,引擎把剛剛寫入的 redo log 改成提交(commit)狀態,更新完成;

示意圖如下所示:

這種將 redolog 的寫入拆分成 prepare 和 commit 兩個步驟的過程稱之為兩階段提交。

redolog 和 binlog 都可以用于表示事務的提交狀態,而兩階段提交就是讓這兩個狀態保持邏輯上的一致。如果不使用兩階段提交,而是先寫其中一個再寫另外一個可能會帶來一些問題。

此時還是使用 update 來舉例。假設當前 id=2,有一個字段 c =0,分別分析以下情況:
先寫 redolog 再寫 binlog
假設先寫 redolog,當 redolog 寫完,但是 binlog 還未寫完的時候,此時 MySQL 突然出現異常導致重啟。由于之前 redolog 已經寫完,系統重啟后,修改的記錄仍然存在,所以恢復后這一行 c 的值是 1。但由于系統重啟,binlog 中并未有這條記錄。之后備份日志的時候,存起來的 binlog 里面就沒有這條語句。然后你會發現,如果需要用這個 binlog 來恢復臨時庫的話,由于這個語句的 binlog 丟失,這個臨時庫就會少了這一次更新,恢復出來的這一行 c 的值就是 0,與原庫的值不同。
先寫 binlog 再寫 redolog
假如先寫 binlog,然后寫 redolog 的時候系統重啟。重啟之后,redolog 中沒有對 c 進行修改的記錄,此時 c 的值還是 0。但是 binlog 里面已經記錄了“把 c 從 0 改成 1”這個日志。所以,在之后用 binlog 來恢復的時候就多了一個事務出來,恢復出來的這一行 c 的值就是 1,與原庫的值不同。

因此,綜上所述,如果是先寫某一個日志再寫另一個日志,就會出現數據庫的狀態與使用 binlog 恢復出來的庫的狀態不一致的情況。

3、undo log

undolog 主要用來記錄某條行記錄被修改之前的狀態,記錄的是修改前的數據。這樣的話,當事務進行回滾時,就可以通過 undolog 將記錄恢復到事務開始前的樣子。事務的原子性和持久性也是依靠 undolog 來實現的。undo log 主要記錄了數據的邏輯變化,比如一條 INSERT 語句,對應一條 DELETE 的 undo log,對于每個 UPDATE 語句,對應一條相反的 UPDATE 的 undo log,這樣在發生錯誤時,就能回滾到事務之前的數據狀態。同時,在進行數據恢復的時候,與 binlog,redolog 結合使用,保證了數據恢復的正確性。

undolog 的作用流程如下所示:

在事務開始之前將修改前的版本寫入到 undo log 中;

開始進行修改,將修改過的數據保存到內存當中;

將 undolog 持久化到磁盤當中;

將數據頁刷回到磁盤當中;

事務提交;

需要注意的是,與 redolog 一樣,undolog 也是要先于數據頁刷回到磁盤當中。在恢復數據時,如果 undolog 是完整的,可以根據 undolog 來回滾事務。

在一個事務當中,可能會對同一條數據進行多次修改,那么是不是每一次修改前的記錄都要記錄到 undolog 中呢?這樣的話,會導致 undolog 日志量太大,此時 redolog 就要上場了。在一個事務當中,如果是對同一條記錄進行修改,undolog 只會記錄事務開始前的原始記錄,當再次對這條記錄進行修改時,redolog 會記錄后續的變化。在數據恢復時,redolog 完成前滾,undolog 完成回滾,二者相互協調完成數據的恢復。過程如下所示:

到此,關于“MySQL 的 binlog、redo log 和 undo log 怎么使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-15發表,共計6691字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 无极县| 醴陵市| 淳化县| 丹棱县| 双牌县| 潢川县| 桃源县| 苍山县| 嵊泗县| 二连浩特市| 嘉善县| 花莲市| 博兴县| 东乌| 怀集县| 武邑县| 清新县| 托里县| 洛扎县| 香港| 北辰区| 兰溪市| 乐业县| 中卫市| 松桃| 加查县| 吴旗县| 福海县| 永寿县| 湟中县| 金塔县| 兴隆县| 盐城市| 高平市| 寿宁县| 故城县| 灵寿县| 定日县| 神木县| 奉新县| 阜新|