Redo Log Buffer 与 LGWR 写入策略
Redo Log Buffer 与 LGWR 写入策略
适用版本:Oracle Database 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
Redo Log Buffer 是 SGA 中的循环缓冲区,缓存 Redo 记录,由 LGWR 进程异步写入 Redo Log 文件[1]。
作用:
- 减少 Redo 写入磁盘的频率
- 批量写入提升 I/O 性能
- 保证事务持久性(commit 时强制写)
2. Redo Log Buffer 结构
2.1 循环缓冲区
Redo Log Buffer (循环使用)
+----------------------------------------+
| ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓ |
| ↑ 已写入 ↑ |
| | | |
| LGWR 写位置 进程分配位置 |
+----------------------------------------+
↑
新 Redo 写入此处
2.2 大小配置
SHOW PARAMETER log_buffer;
-- 默认 14MB(19c)
-- 最小 64KB
-- 最大 与 OS 相关(通常 4GB)
大小建议:
- OLTP:64MB - 256MB
- 高写入 OLTP:512MB
- 不宜过大:影响实例恢复
3. Redo 记录结构
每条 Redo 记录包含:
| 字段 | 说明 |
|---|---|
| RBA | Redo Block Address(位置标识) |
| SCN | System Change Number |
| Change Vector | 数据变更内容 |
| Transaction ID | 事务标识 |
| Undo 信息 | 对应的 Undo 记录位置 |
Redo 记录示例:
RBA=(0x245, 0x400, 0x10), SCN=1234567890
Change #1: UPDATE block 4, offset 1024, old=1000, new=5000
Transaction ID: 0x0001.012.00001234
Undo: UBAn=0x0002.045.000005678
4. LGWR 写入触发条件
LGWR 进程在以下情况触发写入[1][2]:
| 触发条件 | 说明 |
|---|---|
| 每 3 秒 | LGWR 定时唤醒 |
| COMMIT | 用户提交时同步写 |
| Buffer 1/3 满 | 或 1MB 数据时 |
| DBWn 写脏块前 | 保证 Redo 先于数据落盘 |
| 日志切换 | 强制写完所有 Redo |
4.1 COMMIT 时的写入
用户 COMMIT:
1. 生成 commit 标记写入 Redo Log Buffer
2. LGWR 立即将 Redo Log Buffer 内容写入 Redo Log 文件
3. LGWR 等待 I/O 完成确认
4. 通知用户 COMMIT 成功
5. 释放事务锁
→ COMMIT 延迟 = Redo 落盘时间
4.2 DBWn 写脏块前
重要原则:WAL(Write-Ahead Logging)
DBWn 在写脏块到数据文件前,必须确保对应的 Redo 已落盘:
DBWn 写脏块 B(修改自 Redo 记录 R):
1. 检查 R 是否已写入 Redo Log
2. 若否,触发 LGWR 写入
3. 等待 LGWR 完成
4. DBWn 写 B 到数据文件
5. Redo Log 文件结构
5.1 日志组与日志成员
Redo Log Group 1: [member 1.1, member 1.2] ← 多路复用
Redo Log Group 2: [member 2.1, member 2.2]
Redo Log Group 3: [member 3.1, member 3.2]
循环使用:1 → 2 → 3 → 1 → 2 → 3 ...
5.2 状态切换
状态:
- CURRENT : 当前正在写入
- ACTIVE : 实例恢复需要,但未归档
- INACTIVE : 已归档,可被覆盖
- CLEARING : 正在清空
- UNUSED : 从未使用
SELECT group#, sequence#, members, bytes/1024/1024 AS mb,
status, archived
FROM v$log;
6. 日志切换(Log Switch)
6.1 触发
- 当前 Redo Log 写满
- 手动执行
ALTER SYSTEM SWITCH LOGFILE - 设置
ARCHIVE_LAG_TARGET强制切换
6.2 切换流程
1. LGWR 停止写入当前组
2. 切换到下一组
3. 触发检查点(CKPT 通知 DBWn 写脏块)
4. ARCn 复制当前组到归档目录
5. 当前组状态变为 INACTIVE
6.3 强制日志切换
-- 手动切换
ALTER SYSTEM SWITCH LOGFILE;
-- 设置归档延迟(强制 30 分钟切换一次)
ALTER SYSTEM SET archive_lag_target=1800 SCOPE=BOTH;
7. 相关视图
-- Redo Log 组信息
SELECT group#, thread#, sequence#, bytes/1024/1024 AS mb,
members, status, archived, first_change#, first_time
FROM v$log;
-- Redo Log 文件成员
SELECT group#, member, status
FROM v$logfile;
-- Redo Log Buffer 统计
SELECT name, value
FROM v$sysstat
WHERE name IN (
'redo entries',
'redo size',
'redo synch time',
'redo synch writes',
'redo buffer allocation retries',
'redo log space requests',
'redo log space wait time'
);
-- LGWR 等待事件
SELECT event, total_waits, time_waited
FROM v$system_event
WHERE event LIKE 'log file%';
8. 常见坑与排错
8.1 log file sync 等待严重
现象:log file sync 等待事件占据 TOP 1。
原因:
- Redo Log 写入慢(磁盘 I/O 瓶颈)
- LGWR 进程性能问题
- 远程 Data Guard 同步延迟
修复:
-- 1. 检查 Redo Log 磁盘性能
-- Linux:
-- dd if=/dev/zero of=/u02/test.dbf bs=8k count=10000 oflag=dsync
-- 2. 使用更快的存储(SSD/NVMe)
-- 3. 调整 Data Guard 同步模式
-- 改为 ASYNC 模式
ALTER SYSTEM SET log_archive_dest_2='SERVICE=stdby ASYNC' SCOPE=BOTH;
-- 4. 考虑 commit 写优化
-- 仅在低数据丢失容忍时使用
ALTER SYSTEM SET commit_write='NOWAIT,BATCH' SCOPE=BOTH;
8.2 Redo Log 切换过频
现象:每小时切换 > 10 次。
修复:
-- 增大 Redo Log 文件大小
ALTER DATABASE ADD LOGFILE GROUP 4 ('/u01/redo04.log') SIZE 1G;
ALTER DATABASE ADD LOGFILE GROUP 5 ('/u01/redo05.log') SIZE 1G;
-- 删除旧的小日志组(先确保不是 CURRENT)
ALTER DATABASE DROP LOGFILE GROUP 1;
-- 推荐大小:每小时切换 3-5 次
8.3 checkpoint not complete
现象:日志切换时报 Checkpoint not complete。
原因:检查点未完成时 LGWR 需要覆盖未归档/未写完的 Redo。
修复:
-- 1. 增加日志组数(至少 4-6 组)
ALTER DATABASE ADD LOGFILE GROUP 6 ('/u01/redo06.log') SIZE 1G;
-- 2. 增大 Redo Log 大小
-- 3. 优化 DBWn 性能
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;
8.4 Redo Buffer 分配重试
现象:redo buffer allocation retries 高。
原因:LGWR 写入速度跟不上 Redo 生成速度。
修复:
-- 1. 增大 Redo Log Buffer
ALTER SYSTEM SET log_buffer=256M SCOPE=SPFILE;
-- 2. 优化 Redo Log 磁盘
-- 3. 减少 Redo 生成(如批量 NOLOGGING)
9. 最佳实践
- Redo Log 多路复用:每组 2-3 个 member,分布不同磁盘
- 合理大小:每小时切换 3-5 次
- 至少 4-6 个日志组:避免 checkpoint not complete
- 快速存储:SSD/NVMe 提升写性能
- 监控 log file sync:等待时间应 < 10ms
- 批量提交:减少 commit 次数
- Data Guard 用 ASYNC:避免同步影响主库
- 专用 Redo 磁盘组(ASM):独立 I/O
10. 参考资料
[1] Oracle Database Concepts 19c, “Redo Log Buffer” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/memory-architecture.html
[2] Oracle Database Administrator’s Guide 19c, “Managing the Redo Log” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-redo-log-files.html
[3] AskTOM, “LGWR and Redo Log Internals” https://asktom.oracle.com/pls/apex/f?p=100:1:0