oGRAC redo日志简介
发表于 2026/05/26
0
oGRAC redo日志简介
- redo日志记录对数据页所做的所有修改操作(如插入、更新、删除)。它采用追加写的方式,顺序写入磁盘上的日志文件。在系统崩溃或故障后,通过重放这些日志,将数据库恢复到故障发生前的状态,确保持久性。
- redo日志会先在内存组好(log_batch),再写到redo文件(log_flush->log_flush_to_disk刷盘),先写日志,再刷脏页。
// log_file_ctrl_bk_t is behind it.
typedef struct st_log_file_head {
knl_scn_t first;
knl_scn_t last;
volatile uint64 write_pos;
uint32 asn;
int32 block_size : 16;
int32 cmp_algorithm : 4;
int32 reserve : 12;
uint32 rst_id;
uint32 checksum;
uint64 first_lsn;
uint64 last_lsn;
uint32 dbid;
uint32 recid;
int64 arch_ctrl_stamp;
int64 real_size;
uint32 dest_id;
uint8 pad[4];
uint8 unused[OG_LOG_HEAD_RESERVED_BYTES]; // padded log_file_head_t to 512 bytes
} log_file_head_t;// log_batch组装后写入磁盘,磁盘读取时是通过地址解析出各个值,所以数据异常时读取时算的size不一定是真实值
typedef struct st_log_batch {
log_batch_id_t head;
knl_scn_t scn;
uint32 padding;
uint32 size; // batch length, include log_batch_t head size
uint32 space_size; // The actual space occupied by the batch
uint8 part_count; // a batch contains multiple buffers,less or queue to buffer count
uint8 version;
uint16 batch_session_cnt;
union {
uint64 raft_index;
uint64 lsn; // max lsn of log groups inside this batch, clustered database not support PAXOS/RAFT
};
uint16 checksum;
bool8 encrypted : 1;
uint8 reserve : 7;
uint8 unused[5];
} log_batch_t;几个概念:
- 脏页:内存中的缓冲页(Buffer Pool)被修改后,内存中的内容与磁盘上的对应页不一致,这种页称为脏页。
- 刷脏页:将内存中的脏页内容写回磁盘上的数据文件的过程。
- 落盘:广义上指任何内存数据(日志、数据页)被写入持久化存储(磁盘、SSD)的动作。这里常特指数据页落盘(即刷脏页)和日志落盘。
- 检查点:检查点是一个数据库事件,系统将所有内存中的脏页(已修改但未写回磁盘的数据页)强制刷写到磁盘,并记录下此时 Redo 日志的最新位置(LSN 或日志文件偏移),然后将这个位置持久化到控制文件。
- pin住:指的是将一个对象固定在内存中,使其不会被换出或失效。
崩溃恢复时:
- 修改已提交:redo重做;
- 修改未提交:undo回滚;
- 刷脏页(
pagewriter或checkpoint)不关心事务状态,它只是将内存页面内容写入磁盘。如果刷入了未提交事务修改的页面,磁盘上就会暂时包含未提交的数据。这没关系,因为恢复时仍然可以通过日志中的事务状态进行回滚。
redo中的几个序列号:
LSN日志序列号
唯一标识每一条日志记录(或每个日志批次 log_batch_t)在日志流中的逻辑位置
- 作用:
(1)用于恢复:确定需要重做的日志起点和终点;
(2)用于检查点:记录脏页对应的最新 LSN,恢复时只需从检查点 LSN 开始重放;
(3)用于事务提交:确保日志已落盘到该 LSN。
- 特点:不是简单的文件偏移,而是与日志记录一一对应的逻辑序号。某些数据库中 LSN 也可能包含文件号和块号的编码,但通常单独作为 64 位整数。
LFN日志文件号
- 作用:
(1)与 ASN、Block ID 结合,可以定位日志在磁盘上的物理位置;
(2)用于日志切换:当当前文件写满时,LFN 递增,创建新的日志文件;
(3)用于归档:归档日志按 LFN 顺序存储。
- 存储:通常与 ASN 一起出现在
log_point_t结构中,表示某个 LSN 对应的物理文件。
ASN 归档序列号
表示日志的归档序号或节点内的日志流序号。有时也用于标识日志批次序号。
WAL 原则:日志先落盘,数据页后落盘
数据库保证:在脏页落盘之前,该页对应的 Redo 日志必须已经安全写入磁盘。这是崩溃恢复的基础。
- 如果事务提交,必须先将该事务产生的 Redo 日志强制刷盘(
log flush),然后才能向客户端返回成功。此时脏页可能还在内存中。 - 如果数据库崩溃,重启后通过读取磁盘上的 Redo 日志,重新执行(重做)那些已提交但尚未落盘的事务修改,从而恢复数据一致性。
相关函数
写盘:
log_flush
log_flush_to_disk读盘:
dtc_rcy_process_batches
<font style="color:#DF2A3F;">dtc_rcy_read_node_log_proc:</font>DTC恢复阶段读盘上的redo
dtc_read_node_log
dtc_rcy_read_node_log
<font style="color:#DF2A3F;">drc_rcy_read_online_log</font>:读盘rcy_write_point位置到read_buf,读取file head
dtc_rcy_read_log
dtc_rcy_read_archived_log
-read_size=0:
dtc_rcy_next_file:读下一个文件
-未结束:
dtc_rcy_read_node_log:继续读日志
-read_size!=0
find_max_lsn_and_move_point:推进读盘位置rcy_write_point:一次覆盖本段读入数据内连续多个 batch,LSN 取最后一个dtc_rcy_fetch_log_batch:读取缓冲区日志进行恢复:每次一个被选中的 batch(全局 LSN 最小)
dtc_rcy_pitr_replay_end
dtc_rcy_process_batch


