一文讀懂 OceanBase 資料庫的SLog日誌
作者簡介:鏡水,一個無限進步的資料庫學徒。
作者簡介:海芊,一個致力於當網紅的 OceanBase 文件工程師。
本文主要介紹 OceanBase 資料庫的 Slog 日誌,從程式碼層面剖析 Slog 日誌的模組結構和工作機制,幫助大家深入理解OceanBase 資料庫的 Slog日誌。
基本概念
我們都知道 OceanBase 資料庫的 Clog 日誌類似於傳統資料庫的 Redo 日誌,因此在分散式場景下需要多副本同步。而 Slog 不一樣,Slog 可以理解為伺服器的本地日誌,是一臺伺服器上一些全域性資訊變更操作(如新增租戶、分割槽建立和新增 SSTable 等)的 redo log。
一個伺服器只擁有一個 Slog 寫入流,也就是說同一臺伺服器上具有不同資源池的不同租戶並不具有單獨的 Slog 檔案,所有租戶的 Slog 寫入請求最後都會匯入伺服器所擁有的 Slog 檔案中。
一條 Slog 日誌記錄的格式為:
從上圖可以看出,Slog 分為三部分,其中每個部分可以理解為一個 log 塊,具有遞增的 log_seq 序號,儲存在
LogEntry
內(log 塊的 header):
1. Logs,有效的 redo log 內容,可能包含多條實際的子 redo log,每條子 log 有子 log_seq(從 0 開始遞增)。
2.NopLog,無意義的 log 內容,只是為了讓整條記錄 4k 對齊。
3.SwitchLog,只在一個 slog 檔案的最後一條記錄出現,包含 next file id,便於切換下一個 Slog 檔案繼續讀取,同時也會包含 padding buffer 做對齊。
程式碼分析
接下來從程式碼層面展開分析 Slog。(由於 NopLog 和 SwtichLog 沒有實際的 redo log 內容,因此這裡不展開分析)
日誌結構
每條 Slog 記錄的 logs 部分(上圖所示的第一部分 log 塊)的格式如下:
ObLogEntry + n *
log content
ObLogEntry
可以理解為整個 log 塊的 header:
struct ObLogEntry {
ObRecordHeader header_;
uint64_t seq_; // 整個 log 的 log_seq
int32_t cmd_; // 該 log 的型別,比如 OB_LOG_NOP 表示該 log 的型別為 NopLog
// 具體見 enum LogCommand
}
struct ObRecordHeader {
int16_t magic_; // magic number
int16_t header_length_; // header length
int16_t version_; // version
int16_t header_checksum_; // header checksum
int64_t timestamp_; //
int32_t data_length_; // length before compress
int32_t data_zlength_; // length after compress, if without compresssion
// data_length_= data_zlength_
int64_t data_checksum_; // record checksum
...
}
n *
log content
在記憶體中由
ObStorageLogActiveTrans
結構進行組織管理,以序列化的形式共同存放在
log_buffer_
:
struct ObStorageLogActiveTrans {
enum common::LogCommand cmd_; // 等同於 ObLogEntry 中的 cmd_
int64_t log_count_; // log_buffer_ 中包含的 log 數量
common::ObLogCursor start_cursor_; // log_buffer_ 中第一條 log 刷盤的位置
// 在 log_buffer_ 刷盤時被賦值
ObStorageLogValidRecordEntry valid_record_;
ObBaseStorageLogBuffer log_buffer_; // 所有 log content 的 buffer
...
}
每個
log content
由一個 log header(
ObBaseStorageLogHeader
結構)和實際的 log data 組成。
struct ObBaseStorageLogHeader {
...
int64_t trans_id_; // 事務 id,每次 Slog 的寫入對應有一個事務 id
int64_t log_seq_; // 每條 log content 在整個 logs 裡的 seq
int64_t subcmd_; // 32bit(main_type)+32bit(sub_type)
// main_type 表示日誌與什麼相關,sub_type 表示該日誌的具體操作型別
// 如main_type = OB_REDO_LOG_PARTITION 表示日誌與分割槽相關,具體見 ObRedoLogMainType
// 如sub_type = REDO_LOG_ADD_PARTITION 表示增加分割槽日誌,每種 main_type 都有單獨對應的 XXXRedoLogSubcmd
int64_t log_len_;
uint64_t tenant_id_;
int64_t data_file_id_;
...
}
每次 Slog 的寫入可以看做是一次事務,包括了 trans begin/n * trans/trans commit,而每個事務的子操作對應著一個
log content
(包括 begin/commit)。
寫入流程
1.
ObBaseStorageLogger::begin
開啟一次 Slog 寫事務:
(1)從
ObBaseStorageLogger
的
ObStorageActiveTrans
池中取出一個元素 trans_entry 用於本次 Slog 寫事務。
(2)向 trans_entry 中 append 一條 begin 日誌,即寫入 trans_entry 的
log_buffer_
。
2.多次呼叫
ObBaseStorageLogger::write_log
:
(1)正常條件下每次呼叫都向 trans_entry 的
log_buffer_
append 一條
log content
。
(2)當 trans_entry 的
log_buffer_
達到上限(512-3*4-4 KB)時,對
log_buffer_
裡已有的 log 內容進行 flush。
(3)當 log 本身長度超出上限(512-3*4-4 KB)時,首先對
log_buffer_
裡已有的 log 內容進行 flush,然後擴大 trans_entry 的
log_buffer_
,將超長 log append 到
log_buffer_
,並再次 flush,最後恢復 trans_entry 的
log_buffer_
大小。
3.
ObBaseStorageLogger::commit
提交(結束)Slog 寫事務:
(1)向 trans_entry 中 append 一條 begin 日誌,即寫入 trans_entry 的
log_buffer_
。
(2)直接對
log_buffer_
進行 flush。
flush 流程
1.
ObBaseStorageLogger::flush_log
對一個
log_buffer_
已滿(或超長 log)的
ObStorageActiveTrans
進行刷盤操作:
(1)呼叫 Slog 寫盤類
ObStorageLogWriter
的
flush_log
函式進行 Slog 落盤。
(2)首先從
ObStorageLogWriter
的
ObStorageLogItem
(結構如下)池中取出一個元素
log_item
,然後使用
log_buffer_
構造 Logs 的 log 塊(
log_buffer_
就對應了前文的 n*
log content
),並依次構造 NopLog 的 log 塊以及 SwitchLog 的 log 塊(如果有的話),最終構造成完整的一條 Slog 記錄(最長為 32 MB)並填充到
log_item
的
buf_
。
(3)
log_item
構造完成後進行寫盤操作(涉及到非同步操作,這裡不做介紹)。
class ObStorageLogItem : public common::ObIBaseLogItem {
...
bool is_inited_;
bool is_local_; // indicate whether buf_ is allocated locally or not
int64_t buf_size_;
char* buf_;
int64_t len_;
common::ObThreadCond flush_cond_;
bool flush_finish_;
int flush_ret_;
}
flush 流程的核心是通過寫流程中得到的 n *
log content
構造出一條完整的 Slog 記錄,通常可以直接用
ObStorageLogItem
結構指代。
示例
上圖是 ob_admin 的 slog_tool 工具所顯示的某 slog 檔案的部分日誌內容。
1.
log_seq
=1 的 redo log 共有三個
log content
,其中每個
log content
都有自身的
sub_seq
;
(1)每個
log content
的 command = 626(
OB_LOG_TABLE_MGR
),表明都是與 TableMgr 相關的 log。
(2)
sub_seq
=1 的子日誌的
main_type
= 3(
OB_REDO_LOG_TABLE_MGR
),表明是與 TableMgr 相關的 log,而
sub_type
在圖中沒有以值的方式標出,實際上其
sub_type
= 8(
REDO_LOG_COMPELTE_SSTABLE
),也就是圖中的 complete sstable 含義。
2.
log_seq
=2 的 log 為第一條 Slog 記錄的 NopLog,因此圖中並沒有顯示該 log,而是隻顯示了
log_seq
=1 以及
log_seq
=3 的 redo log。
優化版本
由於一次事務的所有 redo log 資料量可能很小,如果每一次事務都直接增加 noplog 構造
ObStorageLogItem
刷盤,空間浪費且頻寬浪費,因此可以聚合多次事務,flush 時將多次事務的 redo log 新增到佇列,真正非同步寫盤時將多次事務的 logs 聚合成新的
ObStorageLogItem
,從而形成如下結構:
checkpoint
這裡不介紹
checkpoint
的具體觸發條件和執行流程,感興趣的同學可以進一步閱讀程式碼。
工作機制
為了加快恢復,Slog 提供
checkpoint
機制,生成
checkpoint
的過程也就是形成後設資料巨集塊的過程,後設資料巨集塊,也就是所謂的
Meta Block
,會寫入
block_file
,Slog 同時會具有一個回放點(
replay_start_point_
),標明瞭 Slog 內尚未生成
checkpoint
的剩餘日誌的起始偏移位置。
Meta Block
的入口點以及 Slog 的回放點都儲存在
Super Block
,想要了解更多相關內容可以閱讀巨集塊或 OBServer 恢復的相關文章。
恢復
OBServer 對於 Slog 日誌需要恢復的資料分為兩部分,一部分是已經
checkpoint
形成
Meta Block
的基線後設資料,另一部分是從 Slog 回放點開始的 Slog 日誌,也就是增量後設資料。
以上便是 OceanBase 資料庫 Slog 的詳細介紹,
更多 知識和乾貨請點選連結 檢視原文及社群:
https:// open.oceanbase.com/arti cles/8500124?sou0c001
最後的最後:
如果大家有任何疑問,可以通過以下方式與我們進行交流:
測試遇到問題?
企業使用者想享受技術顧問的免費一對一諮詢服務?
快加入 OB 創計劃→
釘釘群:33254054
今日之星,明日之星都不如你留下的星星(⭐️️)
我們想讓 Github 上優質的開源專案被更多人看到。
文件都是我們精心整理。如果有幫助的話 求個star(◕ᴗ◕✿),鼓勵鼓勵我們喲!
也歡迎大家給我們 提 issue,請點選 這裡。運營小姐姐在此跪謝️️ ❥(^_-)
歡迎大家一起參與 社群貢獻,指南請參考看 這裡
社群答疑:請點選 這裡
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70005215/viewspace-2794952/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- OceanBase 原始碼解讀(七):一文讀懂資料庫索引實現原理原始碼資料庫索引
- 一文讀懂資料庫發展史資料庫
- 一文讀懂資料庫70年發展史資料庫
- 一文讀懂知識圖譜與向量資料庫的異同資料庫
- 一文讀懂如何實施資料治理?
- 一文讀懂SpringMVC中的資料繫結SpringMVC
- 一文讀懂大資料實時計算大資料
- 一文讀懂圖資料庫 Nebula Graph 訪問控制實現原理資料庫
- 一文讀懂資料平臺的發展歷史
- 一文讀懂資料庫中的樂觀鎖和悲觀鎖和MVVC資料庫
- 一文讀懂選擇資料湖還是資料倉儲
- 一文讀懂遊戲資料分析指標的應用遊戲指標
- 一文讀懂資料鑽取-騰訊雲開發者社群
- 一文讀懂mavenMaven
- MySQL資料庫中的日誌檔案---(1)錯誤日誌MySql資料庫
- 生死時刻:一文讀懂Facebook資料洩密始末
- 超級乾貨 :一文讀懂資料視覺化視覺化
- 一文讀懂資料平臺建設的演進歷程
- 一文讀懂最近流行的CNN架構(附學習資料)CNN架構
- oracle資料庫mmnl日誌很大Oracle資料庫
- 分析資料庫日誌(LogMiner)資料庫
- 清除SQL Server資料庫日誌SQLServer資料庫
- OceanBase 原始碼解讀(八):事務日誌的提交和回放原始碼
- 資料庫altert日誌中的GTX提示資料庫
- MySQL資料庫中的日誌檔案---(3)慢查詢日誌MySql資料庫
- MySQL資料庫中的日誌檔案---(2)普通查詢日誌MySql資料庫
- 一文讀懂天翼雲自研 TeleDB 資料庫五大關鍵特性資料庫
- 一文讀懂微核心
- 一文讀懂特徵工程特徵工程
- 一文讀懂資料戰略及如何賦能業務成功
- 資料變金礦:一文讀懂序列模型(附用例)模型
- 【獨家】一文讀懂大資料計算框架與平臺大資料框架
- 一文讀懂:本地資料湖丨資料倉儲丨雲資料湖的利與弊
- Oracle資料庫重做日誌及歸檔日誌的工作原理說明Oracle資料庫
- 瀚高資料庫日誌挖掘方法資料庫
- 資料庫映象和日誌傳送資料庫
- SQL Server 檢視資料庫日誌SQLServer資料庫
- IIS 日誌匯入到資料庫的方法資料庫