---
title: oGRAC redo日志简介-官方技术文章-鲲鹏社区
description: 本文主要介绍oGRAC redo日志
keywords: GRAC,日志简介,官方技术文章,鲲鹏社区,几个概念,崩溃恢复时,中的几个序列,LSN
url: https://www.hikunpeng.com/developer/techArticles/20260526-1?envFlag=1
section: (其他)
---

# oGRAC redo日志简介-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20260526-1?envFlag=1
描述: 本文主要介绍oGRAC redo日志
关键词: GRAC,日志简介,官方技术文章,鲲鹏社区,几个概念,崩溃恢复时,中的几个序列,LSN

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

oGRAC redo日志简介

oGRAC redo日志简介

oGRAC

发表于 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

本页内容
