想跟大家聊聊關於 mysql 中的兩個小的知識點:redo log 和 binlog
。
redo log
:InnoDB 儲存引擎層方面的日誌,所以如果你使用的儲存引擎不是 InnoDB 的話,那就根本談不上 redo log。
binlog
: MySQL Server 層記錄的日誌,所以不管是用的什麼儲存引擎,只要是MySQL 都是會有binlog 的存在,在做MySQL 主從複製的時候,利用的就是binlog。
接下來,我們就詳細來看看它們都分別做了啥?
為什麼要有這個 redo log 日誌檔呢?
這裡,我們可以舉個例子,現在我們想對資料庫的資料進行修改操作,現在一條update 語句過來,一般update 操作都伴隨著查詢的操作,得先找到這條數據,然後再進行更新操作對吧。
如果數據量比較小還好,很快就能找到並且更新完畢,但是如果數據量比較大,裡面有一億條數據,怎麼辦?而且更新操作肯定是要寫到磁碟上去的,那這中間的 IO 成本呢?
如果我有好幾十個 update 語句先後更新呢?這樣想的話,你就能想到,就這些操作,成本就高的不行,那能不能降低一下這些成本呢?
這時候,redo log 就發揮作用了。當有記錄更新的時候, InnoDB 引擎就會先把記錄寫到 redo log 裡面去,同時更新內存,這樣就算是更新這條資料成功了。
但是此時,它並沒有更新到磁碟上去對吧?別擔心, InnoDB 會在恰當的時候,把這條及記錄更新到磁碟上去。
這樣的想法或技術,有個專有名詞: WAL 技術,也就是 WriteAheadLogging ,核心就是先寫日誌,再寫磁碟。
redo log 不能一直寫吧?
redo log 的大小是固定的,前面的內容會被覆蓋,一旦寫滿,就會觸發 redo log 到磁碟的同步,以便騰出空間記錄後面的修改。
資料庫發生宕機或重啟,資料也不會遺失。
因為有了 redo log ,之前提交的記錄都還在,只需要根據 redo log 裡面的記錄進行相應恢復就可以了。
binlog 是 MySQL Server 層的記錄日誌。
redo log 和 binlog 的區別:
redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實現的,所有的引擎都是可以的。
redo log 是實體日誌,記錄的是」在XXX 頁上做了XXX 修改」;binlog 是邏輯日誌,例如」給id = 2 這一行的c 欄位加1 」。
redo log 是有固定大小的,所以它的空間會用完,如果用完的話,一定要進行一些寫入磁碟的操作才可以繼續;binlog 是可以追加寫入的,也就是binlog 沒有空間的概念,一直寫就行了。
binlog 以事件的形式記錄了所有的DDL 和DML 語句(因為它記錄的是操作而不是資料值,屬於邏輯日誌),可以用來做主從複製和資料恢復。
在開啟了 binlog 功能的情況下,我們可以把 binlog 匯出成 SQL 語句,把所有的操作重播一遍,來實現資料的復原。
有了這兩個日誌之後,我們來看看一條更新語句是怎麼執行的(redo 不能一次寫入了):
例如一條語句:update user set name='小馬' where id=1;
先查詢到這條數據,如果有緩存,也會用到快取。
把 name 改成小馬
,然後呼叫引擎的 API 接口,寫入這一行資料到內存,同時記錄 redo log。這時 redo log 進入 prepare 狀態,然後告訴執行器,執行完成了,可以隨時提交。
執行器收到通知後記錄 binlog,然後呼叫儲存引擎接口,設定 redo log為 commit 狀態。
更新完成。
你能發現 redo log 竟然是先 prepare 狀態,等 binlog 寫完之後,才是 commit 狀態,這種方式就叫」兩階段提交」。為什麼會有這種方式呢?
redo log 和 binlog 都可以用來表示交易的提交狀態,而兩階段提交
就是讓這兩個狀態保持邏輯上的一致。
可以假設一下,如果不採用這種方式,而是就先寫 redo log ,再寫 binlog ,會怎麼樣?如果在寫 binlog 時,發生了異常,更新操作已經到 redo log 中了,但是此時 binlog 並沒有進行更新,是不是出現了資料不一致?
先寫 binlog 再寫 redo log 也是一樣的道理。所以,寫完時,先讓 redo log 處於 prepare 狀態,等 binlog 寫完之後,再讓 redo log 處於 commit 狀態,這樣就保持了邏輯上的一致。
以上是mysql中redo log和binlog的差別有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!