Skip to content

Oracle Redo Log与Undo Log

Redo Log 和 Undo Log 是 Oracle 数据库中至关重要的日志文件,它们共同保证了数据库的一致性、完整性和可恢复性。理解这两种日志的工作原理对于 DBA 进行日常运维、备份恢复和性能调优至关重要。

Redo Log 概述

Redo Log 的定义

Redo Log(重做日志)是 Oracle 数据库用于记录所有数据修改操作的日志文件。它包含了恢复数据库所需的所有信息,可以将数据库恢复到任意时间点。

Redo Log 的作用

  • 崩溃恢复:当数据库实例意外崩溃时,Oracle 可以使用 Redo Log 恢复未写入数据文件的修改
  • 介质恢复:当数据文件损坏时,Oracle 可以使用 Redo Log 和备份文件恢复数据库
  • 实例恢复:当数据库实例正常关闭时,Oracle 会将所有修改写入数据文件,不需要 Redo Log 进行恢复
  • 数据复制:Oracle Data Guard 和 Streams 等技术使用 Redo Log 进行数据复制

Redo Log 的结构

Redo Log 组

  • Redo Log 以组(Group)的形式组织,每个组包含一个或多个成员(Member)
  • 每个组的成员是完全相同的副本,用于冗余和容错
  • Oracle 至少需要两个 Redo Log 组,以实现日志切换

Redo Log 成员

  • 每个成员是一个物理文件,存储在磁盘上
  • 同一组的成员通常存储在不同的磁盘上,以提高可靠性
  • 成员的大小和数量可以根据业务需求配置

Redo Log 循环使用

  • Oracle 按顺序使用 Redo Log 组,当一个组写满后,会切换到下一个组
  • 当所有组都写满后,Oracle 会覆盖最早的组(如果该组的内容已经写入数据文件)
  • 这种循环使用机制确保了 Redo Log 不会无限增长

Redo Log 管理

Redo Log 组管理

sql
-- 查看 Redo Log 组信息
SELECT group#, thread#, sequence#, bytes, members, status FROM v$log;

-- 查看 Redo Log 成员信息
SELECT group#, member, status FROM v$logfile;

-- 添加 Redo Log 组
ALTER DATABASE ADD LOGFILE GROUP 4 ('+DATA/orcl/redo04a.log', '+FRA/orcl/redo04b.log') SIZE 200M;

-- 添加 Redo Log 成员
ALTER DATABASE ADD LOGFILE MEMBER '+DATA/orcl/redo01c.log' TO GROUP 1;

-- 删除 Redo Log 成员
ALTER DATABASE DROP LOGFILE MEMBER '+DATA/orcl/redo01c.log';

-- 删除 Redo Log 组
ALTER DATABASE DROP LOGFILE GROUP 4;

-- 强制日志切换
ALTER SYSTEM SWITCH LOGFILE;

-- 强制检查点
ALTER SYSTEM CHECKPOINT;

-- 清除 Redo Log 组
ALTER DATABASE CLEAR LOGFILE GROUP 3;

-- 清除未归档的 Redo Log 组
ALTER DATABASE CLEAR UNARCHIVED LOGFILE GROUP 3;

Redo Log 大小与数量优化

大小优化

  • 过小的 Redo Log 会导致频繁的日志切换,增加系统开销
  • 过大的 Redo Log 会导致恢复时间过长
  • 推荐大小:500MB 到 2GB 之间,根据业务写入量调整
  • 监控日志切换频率:理想情况是每 15-30 分钟切换一次
sql
-- 查看日志切换频率
SELECT TO_CHAR(first_time, 'YYYY-MM-DD HH24') AS hour, COUNT(*) AS log_switches
FROM v$log_history
GROUP BY TO_CHAR(first_time, 'YYYY-MM-DD HH24')
ORDER BY 1 DESC;

数量优化

  • 至少需要 2 个 Redo Log 组
  • 推荐数量:4-10 个组,根据业务写入量和磁盘数量调整
  • 每个组的成员数量:建议 2-3 个成员,存储在不同的磁盘上

Redo Log 故障处理

单个成员损坏

sql
-- 查看损坏的成员
SELECT group#, member, status FROM v$logfile WHERE status = 'INVALID';

-- 删除损坏的成员
ALTER DATABASE DROP LOGFILE MEMBER '+DATA/orcl/redo01a.log';

-- 添加新成员
ALTER DATABASE ADD LOGFILE MEMBER '+DATA/orcl/redo01a.log' TO GROUP 1;

整个组损坏

sql
-- 如果组未激活且未归档
ALTER DATABASE CLEAR UNARCHIVED LOGFILE GROUP 2;

-- 如果组已激活
-- 1. 切换日志
ALTER SYSTEM SWITCH LOGFILE;
-- 2. 强制检查点
ALTER SYSTEM CHECKPOINT;
-- 3. 清除日志组
ALTER DATABASE CLEAR LOGFILE GROUP 2;

归档日志(Archive Log)

归档日志的定义

归档日志(Archive Log)是已写满的 Redo Log 组的副本,用于长期存储和介质恢复。

归档模式

  • NOARCHIVELOG 模式:不保留已写满的 Redo Log,适用于测试环境
  • ARCHIVELOG 模式:保留已写满的 Redo Log,适用于生产环境

归档日志的作用

  • 介质恢复:当数据文件损坏时,可以使用归档日志和备份文件恢复数据库
  • 时间点恢复:可以将数据库恢复到任意时间点
  • 数据复制:用于 Oracle Data Guard 和 Streams 等技术
  • 审计和合规:用于审计和满足合规要求

归档模式管理

sql
-- 查看当前归档模式
SELECT log_mode FROM v$database;

-- 切换到归档模式
-- 1. 关闭数据库
SHUTDOWN IMMEDIATE;
-- 2. 启动到 mount 模式
STARTUP MOUNT;
-- 3. 启用归档模式
ALTER DATABASE ARCHIVELOG;
-- 4. 打开数据库
ALTER DATABASE OPEN;

-- 切换到非归档模式
-- 1. 关闭数据库
SHUTDOWN IMMEDIATE;
-- 2. 启动到 mount 模式
STARTUP MOUNT;
-- 3. 禁用归档模式
ALTER DATABASE NOARCHIVELOG;
-- 4. 打开数据库
ALTER DATABASE OPEN;

-- 查看归档日志信息
SELECT * FROM v$archived_log;

-- 查看归档日志目的地
SHOW PARAMETER log_archive_dest;

-- 设置归档日志目的地
ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=+FRA' SCOPE=BOTH;
ALTER SYSTEM SET log_archive_dest_2 = 'SERVICE=STANDBY_DB ASYNC' SCOPE=BOTH;

-- 手动归档
ALTER SYSTEM ARCHIVE LOG CURRENT;

-- 归档特定日志
ALTER SYSTEM ARCHIVE LOG SEQUENCE 100;

归档日志管理

归档日志清理

sql
-- 使用 RMAN 清理归档日志
RMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';

-- 使用 OS 命令清理(不推荐)
-- rm -f /archivelog/*.arc

-- 查看归档日志使用率
SELECT * FROM v$recovery_file_dest;

归档日志压缩

sql
-- 启用归档日志压缩
ALTER SYSTEM SET log_archive_compress = TRUE SCOPE=BOTH;

-- 查看归档日志压缩设置
SHOW PARAMETER log_archive_compress;

Undo Log 概述

Undo Log 的定义

Undo Log(撤销日志)是 Oracle 数据库用于记录数据修改前的旧值的日志文件。它包含了回滚事务所需的所有信息。

Undo Log 的作用

  • 事务回滚:当事务执行 ROLLBACK 命令时,Oracle 可以使用 Undo Log 恢复数据的旧值
  • 一致性读:当事务执行 SELECT 语句时,Oracle 可以使用 Undo Log 生成数据的一致性视图
  • 闪回查询:Oracle 11g 及以上版本支持使用 Undo Log 执行闪回查询
  • 约束检查:Oracle 使用 Undo Log 检查约束的有效性

Undo Log 的结构

Undo 表空间

  • Undo Log 存储在 Undo 表空间中
  • Oracle 10g 及以上版本推荐使用自动 Undo 管理

Undo 段

  • Undo 表空间包含多个 Undo 段
  • 每个 Undo 段包含多个区(Extent)
  • 每个区包含多个数据块(Block)

Undo 数据

  • 每个数据修改操作会生成一条 Undo 记录
  • Undo 记录包含数据修改前的旧值和事务信息
  • Undo 记录由事务 ID 标识

Undo Log 管理

Undo 表空间管理

sql
-- 查看当前 Undo 表空间
SELECT name FROM v$tablespace WHERE name LIKE 'UNDO%';

-- 查看 Undo 表空间使用情况
SELECT tablespace_name, status, contents FROM dba_tablespaces WHERE contents = 'UNDO';

-- 查看 Undo 段信息
SELECT segment_name, status, tablespace_name FROM dba_rollback_segs;

-- 创建 Undo 表空间
CREATE UNDO TABLESPACE undo_new DATAFILE '+DATA' SIZE 100M AUTOEXTEND ON NEXT 20M MAXSIZE 1000M;

-- 切换 Undo 表空间
ALTER SYSTEM SET undo_tablespace = undo_new SCOPE=BOTH;

-- 删除旧的 Undo 表空间
DROP TABLESPACE undo_old INCLUDING CONTENTS AND DATAFILES;

-- 查看 Undo 表空间统计信息
SELECT * FROM v$undostat;

Undo 相关参数设置

sql
-- 查看 Undo 相关参数
SHOW PARAMETER undo;

-- 设置 Undo 管理方式(自动)
ALTER SYSTEM SET undo_management = AUTO SCOPE=SPFILE;

-- 设置 Undo 表空间
ALTER SYSTEM SET undo_tablespace = undo SCOPE=SPFILE;

-- 设置 Undo 保留时间(秒)
ALTER SYSTEM SET undo_retention = 3600 SCOPE=SPFILE;

-- 设置 Undo 表空间自动扩展
ALTER DATABASE DATAFILE '+DATA/orcl/datafile/undo.259.1012345678' AUTOEXTEND ON NEXT 20M MAXSIZE 1000M;

Undo 表空间优化

大小优化

sql
-- 计算 Undo 表空间所需大小
-- 公式:Undo Size = ( undo_retention * (redo_block_writes / redo_blocks_per_undo_block) ) / (60 * 60 * 24)

-- 查看 Undo 表空间使用情况
SELECT tablespace_name, 
       ROUND(total_bytes/1024/1024, 2) AS total_mb, 
       ROUND(used_bytes/1024/1024, 2) AS used_mb, 
       ROUND(free_bytes/1024/1024, 2) AS free_mb
FROM (
  SELECT tablespace_name, 
         SUM(bytes) AS total_bytes,
         SUM(CASE WHEN status != 'FREE' THEN bytes ELSE 0 END) AS used_bytes,
         SUM(CASE WHEN status = 'FREE' THEN bytes ELSE 0 END) AS free_bytes
  FROM dba_free_space
  WHERE tablespace_name LIKE 'UNDO%'
  GROUP BY tablespace_name
);

保留时间优化

sql
-- 查看 Undo 保留时间建议值
SELECT MAX(query_len) AS max_query_len, 
       ROUND(MAX(undoblks) * (SELECT block_size FROM dba_tablespaces WHERE tablespace_name LIKE 'UNDO%') / 1024/1024, 2) AS required_mb
FROM v$undostat;

-- 设置合适的 Undo 保留时间
ALTER SYSTEM SET undo_retention = 7200 SCOPE=SPFILE;

Undo 表空间故障处理

Undo 表空间损坏

sql
-- 启动到 mount 模式
STARTUP MOUNT;

-- 禁用 Undo 自动管理
ALTER SYSTEM SET undo_management = MANUAL SCOPE=SPFILE;

-- 打开数据库
ALTER DATABASE OPEN;

-- 创建新的 Undo 表空间
CREATE UNDO TABLESPACE undo_new DATAFILE '+DATA' SIZE 100M;

-- 启用 Undo 自动管理
ALTER SYSTEM SET undo_management = AUTO SCOPE=SPFILE;
ALTER SYSTEM SET undo_tablespace = undo_new SCOPE=SPFILE;

-- 重启数据库
SHUTDOWN IMMEDIATE;
STARTUP;

-- 删除旧的 Undo 表空间
DROP TABLESPACE undo_old INCLUDING CONTENTS AND DATAFILES;

ORA-01555: Snapshot too old 错误

  • 原因:Undo 表空间不足或 Undo 保留时间过短
  • 解决方案
    1. 增加 Undo 表空间大小
    2. 延长 Undo 保留时间
    3. 优化长运行的查询
sql
-- 增加 Undo 表空间大小
ALTER TABLESPACE undo ADD DATAFILE '+DATA' SIZE 100M AUTOEXTEND ON;

-- 延长 Undo 保留时间
ALTER SYSTEM SET undo_retention = 7200 SCOPE=SPFILE;

闪回功能

闪回查询

sql
-- 闪回查询到指定时间点
SELECT * FROM employees AS OF TIMESTAMP TO_TIMESTAMP('2024-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') WHERE employee_id = 100;

-- 闪回查询到指定 SCN
SELECT * FROM employees AS OF SCN 1000000 WHERE employee_id = 100;

闪回表

sql
-- 启用表闪回
ALTER TABLE employees ENABLE ROW MOVEMENT;

-- 闪回表到指定时间点
FLASHBACK TABLE employees TO TIMESTAMP TO_TIMESTAMP('2024-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS');

-- 闪回表到指定 SCN
FLASHBACK TABLE employees TO SCN 1000000;

-- 禁用表闪回
ALTER TABLE employees DISABLE ROW MOVEMENT;

闪回数据库

sql
-- 查看闪回数据库状态
SELECT flashback_on FROM v$database;

-- 启用闪回数据库
-- 1. 关闭数据库
SHUTDOWN IMMEDIATE;
-- 2. 启动到 mount 模式
STARTUP MOUNT;
-- 3. 启用闪回数据库
ALTER DATABASE FLASHBACK ON;
-- 4. 打开数据库
ALTER DATABASE OPEN;

-- 闪回数据库到指定时间点
-- 1. 关闭数据库
SHUTDOWN IMMEDIATE;
-- 2. 启动到 mount 模式
STARTUP MOUNT;
-- 3. 闪回数据库
FLASHBACK DATABASE TO TIMESTAMP TO_TIMESTAMP('2024-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS');
-- 4. 打开数据库(只读模式验证)
ALTER DATABASE OPEN READ ONLY;
-- 5. 如果验证成功,打开数据库(重置日志)
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE OPEN RESETLOGS;

最佳实践

Redo Log 最佳实践

  1. 使用多个 Redo Log 组:推荐 4-10 个组,避免日志切换过于频繁
  2. 合理设置 Redo Log 大小:推荐 500MB 到 2GB 之间,根据业务写入量调整
  3. 将 Redo Log 成员存储在不同磁盘上:提高可靠性和性能
  4. 使用 ARCHIVELOG 模式:生产环境必须使用 ARCHIVELOG 模式
  5. 合理设置归档日志目的地:推荐将归档日志存储在与数据文件不同的磁盘上
  6. 定期清理归档日志:避免归档日志占用过多磁盘空间
  7. 监控 Redo Log 切换频率:理想情况是每 15-30 分钟切换一次

Undo Log 最佳实践

  1. 使用自动 Undo 管理:Oracle 10g 及以上版本推荐使用自动 Undo 管理
  2. 合理设置 Undo 表空间大小:根据业务写入量和长查询需求调整
  3. 设置合适的 Undo 保留时间:根据闪回查询需求调整
  4. 使用多个 Undo 表空间:方便维护和迁移
  5. 监控 Undo 表空间使用情况:定期检查 Undo 表空间使用率
  6. 避免长运行的查询:长运行的查询会占用大量 Undo 空间
  7. 启用行移动:如果需要使用闪回表功能

归档日志最佳实践

  1. 使用快速恢复区(Fast Recovery Area):方便管理归档日志和备份文件
  2. 合理设置快速恢复区大小:根据备份和归档日志需求调整
  3. 定期备份归档日志:避免归档日志丢失
  4. 使用 RMAN 管理归档日志:推荐使用 RMAN 进行归档日志的备份和清理
  5. 监控归档日志使用率:定期检查归档日志使用率,避免空间不足

版本差异

版本特性
Oracle 11g增强了闪回功能,引入闪回数据归档
Oracle 12c支持多租户环境的 Redo Log 和 Undo Log 管理
Oracle 19c优化了 Redo Log 写入性能,增强了 Undo 表空间管理
Oracle 23c引入了新的日志压缩算法,优化了 Undo 数据管理

常见问题(FAQ)

Q1: 如何查看 Redo Log 信息?

A1: 使用以下查询:

sql
-- 查看 Redo Log 组信息
SELECT group#, thread#, sequence#, bytes, members, status FROM v$log;

-- 查看 Redo Log 成员信息
SELECT group#, member, status FROM v$logfile;

Q2: 如何查看 Undo 表空间使用情况?

A2: 使用以下查询:

sql
SELECT tablespace_name, 
       ROUND(total_bytes/1024/1024, 2) AS total_mb, 
       ROUND(used_bytes/1024/1024, 2) AS used_mb, 
       ROUND(free_bytes/1024/1024, 2) AS free_mb
FROM (
  SELECT tablespace_name, 
         SUM(bytes) AS total_bytes,
         SUM(CASE WHEN status != 'FREE' THEN bytes ELSE 0 END) AS used_bytes,
         SUM(CASE WHEN status = 'FREE' THEN bytes ELSE 0 END) AS free_bytes
  FROM dba_free_space
  WHERE tablespace_name LIKE 'UNDO%'
  GROUP BY tablespace_name
);

Q3: 如何切换归档模式?

A3: 切换归档模式的步骤:

sql
-- 关闭数据库
SHUTDOWN IMMEDIATE;
-- 启动到 mount 模式
STARTUP MOUNT;
-- 启用归档模式
ALTER DATABASE ARCHIVELOG;
-- 打开数据库
ALTER DATABASE OPEN;

Q4: 如何处理 ORA-01555: Snapshot too old 错误?

A4: 处理方法:

  1. 增加 Undo 表空间大小:ALTER TABLESPACE undo ADD DATAFILE '+DATA' SIZE 100M AUTOEXTEND ON;
  2. 延长 Undo 保留时间:ALTER SYSTEM SET undo_retention = 7200 SCOPE=SPFILE;
  3. 优化长运行的查询:分解长查询或增加查询条件

Q5: 如何执行闪回查询?

A5: 执行闪回查询的方法:

sql
SELECT * FROM employees AS OF TIMESTAMP TO_TIMESTAMP('2024-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') WHERE employee_id = 100;

Q6: 如何清理归档日志?

A6: 使用 RMAN 清理归档日志:

sql
RMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';

相关命令速查

命令用途
SELECT * FROM v$log;查看 Redo Log 组信息
SELECT * FROM v$logfile;查看 Redo Log 成员信息
ALTER SYSTEM SWITCH LOGFILE;强制日志切换
ALTER SYSTEM CHECKPOINT;强制检查点
SELECT log_mode FROM v$database;查看归档模式
ALTER DATABASE ARCHIVELOG;启用归档模式
ALTER DATABASE NOARCHIVELOG;禁用归档模式
SELECT * FROM v$undostat;查看 Undo 统计信息
ALTER SYSTEM SET undo_tablespace = undo_new;切换 Undo 表空间
FLASHBACK TABLE employees TO TIMESTAMP;闪回表
FLASHBACK DATABASE TO TIMESTAMP;闪回数据库

总结

Redo Log 和 Undo Log 是 Oracle 数据库中至关重要的日志文件,它们共同保证了数据库的一致性、完整性和可恢复性。DBA 应该深入理解这两种日志的工作原理,合理配置和管理它们,以确保数据库的稳定高效运行。通过遵循最佳实践,DBA 可以提高数据库的可靠性和性能,减少故障恢复时间,满足业务的高可用性需求。