日志系統主要有redo log(重做日志)和binlog(歸檔日志)。redo log是InnoDB存儲引擎層的日志,binlog是MySQL Server層記錄的日志, 兩者都是記錄了某些操作的日志(不是所有)自然有些重復(但兩者記錄的格式不同)。
圖來自極客時間的mysql實踐,該圖是描述的是MySQL的邏輯架構。
redo log日志模塊
redo log是InnoDB存儲引擎層的日志,又稱重做日志文件,用於記錄事務操作的變化,記錄的是數據修改之后的值,不管事務是否提交都會記錄下來。在實例和介質失敗(media failure)時,redo log文件就能派上用場,如數據庫掉電,InnoDB存儲引擎會使用redo log恢復到掉電前的時刻,以此來保證數據的完整性。
在一條更新語句進行執行的時候,InnoDB引擎會把更新記錄寫到redo log日志中,然后更新內存,此時算是語句執行完了,然后在空閑的時候或者是按照設定的更新策略將redo log中的內容更新到磁盤中,這里涉及到WAL
即Write Ahead logging
技術,他的關鍵點是先寫日志,再寫磁盤。
有了redo log日志,那么在數據庫進行異常重啟的時候,可以根據redo log日志進行恢復,也就達到了crash-safe
。
redo log日志的大小是固定的,即記錄滿了以后就從頭循環寫。
圖片來自極客時間,該圖展示了一組4個文件的redo log日志,checkpoint之前表示擦除完了的,即可以進行寫的,擦除之前會更新到磁盤中,write pos是指寫的位置,當write pos和checkpoint相遇的時候表明redo log已經滿了,這個時候數據庫停止進行數據庫更新語句的執行,轉而進行redo log日志同步到磁盤中。
binlog日志模塊
binlog是屬於MySQL Server層面的,又稱為歸檔日志,屬於邏輯日志,是以二進制的形式記錄的是這個語句的原始邏輯,依靠binlog是沒有crash-safe
能力的
redo log和binlog區別
- redo log是屬於innoDB層面,binlog屬於MySQL Server層面的,這樣在數據庫用別的存儲引擎時可以達到一致性的要求。
- redo log是物理日志,記錄該數據頁更新的內容;binlog是邏輯日志,記錄的是這個更新語句的原始邏輯
- redo log是循環寫,日志空間大小固定;binlog是追加寫,是指一份寫到一定大小的時候會更換下一個文件,不會覆蓋。
- binlog可以作為恢復數據使用,主從復制搭建,redo log作為異常宕機或者介質故障后的數據恢復使用。
一條更新語句執行的順序
update T set c=c+1 where ID=2;
- 執行器先找引擎取 ID=2 這一行。ID 是主鍵,引擎直接用樹搜索找到這一行。如果 ID=2 這一行所在的數據頁本來就在內存中,就直接返回給執行器;否則,需要先從磁盤讀入內存,然后再返回。
- 執行器拿到引擎給的行數據,把這個值加上 1,比如原來是 N,現在就是 N+1,得到新的一行數據,再調用引擎接口寫入這行新數據。
- 引擎將這行新數據更新到內存中,同時將這個更新操作記錄到 redo log 里面,此時 redo log 處於 prepare 狀態。然后告知執行器執行完成了,隨時可以提交事務。
- 執行器生成這個操作的 binlog,並把 binlog 寫入磁盤。
- 執行器調用引擎的提交事務接口,引擎把剛剛寫入的 redo log 改成提交(commit)狀態,更新完成。
這個update語句的執行流程圖,圖中淺色框表示是在 InnoDB 內部執行的,深色框表示是在執行器中執行的。
https://www.linuxidc.com/Linux/2018-11/155431.htm
----------------------------------------------------
innodb事務日志包括redo log和undo log。redo log是重做日志,提供前滾操作,undo log是回滾日志,提供回滾操作。
undo log不是redo log的逆向過程,其實它們都算是用來恢復的日志:
1.redo log通常是物理日志,記錄的是數據頁的物理修改,而不是某一行或某幾行修改成怎樣怎樣,它用來恢復提交后的物理數據頁(恢復數據頁,且只能恢復到最后一次提交的位置)。
2.undo用來回滾行記錄到某個版本。undo log一般是邏輯日志,根據每行記錄進行記錄。
https://juejin.im/entry/5ba0a254e51d450e735e4a1f
----------------------------------------------------
一、重做日志(redo log)
作用:
確保事務的持久性。防止在發生故障的時間點,尚有臟頁未寫入磁盤,在重啟mysql服務的時候,根據redo log進行重做,從而達到事務的持久性這一特性。
二、回滾日志(undo log)
作用:
保存了事務發生之前的數據的一個版本,可以用於回滾,同時可以提供多版本並發控制下的讀(MVCC),也即非鎖定讀
三、二進制日志(binlog):
作用:
用於復制,在主從復制中,從庫利用主庫上的binlog進行重播,實現主從同步。
用於數據庫的基於時間點的還原。
https://blog.csdn.net/u012834750/article/details/79533866
--------------------------------------------------------
數據庫數據存放的文件稱為data file;日志文件稱為log file;數據庫數據是有緩存的,如果沒有緩存,每次都寫或者讀物理disk,那性能就太低下了。數據庫數據的緩存稱為data buffer,日志(redo)緩存稱為log buffer;既然數據庫數據有緩存,就很難保證緩存數據(臟數據)與磁盤數據的一致性。比如某次數據庫操作:
update driver_info set driver_status = 2 where driver_id = 10001;
更新driver_status字段的數據會存放在緩存中,等待存儲引擎將driver_status刷新data_file,並返回給業務方更新成功。如果此時數據庫宕機,緩存中的數據就丟失了,業務方卻以為更新成功了,數據不一致,也沒有持久化存儲。
上面的問題就可以通過事務的ACID特性來保證。
BEGIN trans;
update driver_info set driver_status = 2 where driver_id = 10001;
COMMIT;
這樣執行后,更新要么成功,要么失敗。業務方的返回和數據庫data file中的數據保持一致。要保證這樣的特性這就不得不說存儲引擎innodb的redo和undo日志。
redo日志、undo日志:
存儲引擎也會為redo undo日志開辟內存緩存空間,log buffer。磁盤上的日志文件稱為log file,是順序追加的,性能非常高,注:磁盤的順序寫性能比內存的寫性能差不了多少。
undo日志用於記錄事務開始前的狀態,用於事務失敗時的回滾操作;redo日志記錄事務執行后的狀態,用來恢復未寫入data file的已成功事務更新的數據。例如某一事務的事務序號為T1,其對數據X進行修改,設X的原值是5,修改后的值為15,那么Undo日志為<T1, X, 5>,Redo日志為<T1, X, 15>。
梳理下事務執行的各個階段:
(1)寫undo日志到log buffer;
(2)執行事務,並寫redo日志到log buffer;
(3)如果innodb_flush_log_at_trx_commit=1,則將redo日志寫到log file,並刷新落盤。
(4)提交事務。
可能有同學會問,為什么沒有寫data file,事務就提交了?
在數據庫的世界里,數據從來都不重要,日志才是最重要的,有了日志就有了一切。
因為data buffer中的數據會在合適的時間 由存儲引擎寫入到data file,如果在寫入之前,數據庫宕機了,根據落盤的redo日志,完全可以將事務更改的數據恢復。好了,看出日志的重要性了吧。先持久化日志的策略叫做Write Ahead Log,即預寫日志。
分析幾種異常情況:
- innodb_flush_log_at_trx_commit=2(innodb_flush_log_at_trx_commit和sync_binlog參數詳解)時,將redo日志寫入logfile后,為提升事務執行的性能,存儲引擎並沒有調用文件系統的sync操作,將日志落盤。如果此時宕機了,那么未落盤redo日志事務的數據是無法保證一致性的。
- undo日志同樣存在未落盤的情況,可能出現無法回滾的情況。
checkpoint:
checkpoint是為了定期將db buffer的內容刷新到data file。當遇到內存不足、db buffer已滿等情況時,需要將db buffer中的內容/部分內容(特別是臟數據)轉儲到data file中。在轉儲時,會記錄checkpoint發生的”時刻“。在故障回復時候,只需要redo/undo最近的一次checkpoint之后的操作。
https://blog.csdn.net/bluejoe2000/article/details/80349499
原文地址:https://blog.csdn.net/u010002184/article/details/88526708