Oracle Redo 日志操作手册
一、基本概念
Oracle 联机重做日志(Online Redo Log)记录数据库所有变更操作,是实例恢复的核心组件。
- 日志组(Log Group):每个数据库至少 2 个组,循环写入
- 日志成员(Log Member):同一组内的多个成员互为镜像,建议每组 2 个成员分布在不同磁盘
- 日志线程(Thread):RAC 环境中每个实例拥有独立的线程,单实例为 Thread 1
- 日志切换(Log Switch):当前组写满后切换到下一组,触发 LGWR 进程
二、查看 Redo 日志信息
sql
-- 查看日志组状态
SELECT GROUP#, THREAD#, SEQUENCE#, BYTES/1024/1024 AS SIZE_MB,
BLOCKSIZE, MEMBERS, ARCHIVED, STATUS
FROM V$LOG
ORDER BY THREAD#, GROUP#;
-- 查看日志成员(文件路径)
SELECT GROUP#, MEMBER, STATUS, TYPE
FROM V$LOGFILE
ORDER BY GROUP#, MEMBER;
-- 查看日志组与成员汇总
SELECT l.GROUP#, l.THREAD#, l.SEQUENCE#,
l.BYTES/1024/1024 AS SIZE_MB,
l.STATUS AS GROUP_STATUS,
lf.MEMBER AS FILE_PATH,
lf.STATUS AS MEMBER_STATUS
FROM V$LOG l
JOIN V$LOGFILE lf ON l.GROUP# = lf.GROUP#
ORDER BY l.THREAD#, l.GROUP#;
-- 查看当前正在使用的日志组
SELECT GROUP#, SEQUENCE#, STATUS FROM V$LOG WHERE STATUS = 'CURRENT';
-- 查看日志切换历史(最近24小时)
SELECT THREAD#, SEQUENCE#, FIRST_TIME, NEXT_TIME,
ROUND((NEXT_TIME - FIRST_TIME) * 24 * 60, 2) AS DURATION_MIN
FROM V$ARCHIVED_LOG
WHERE FIRST_TIME > SYSDATE - 1
ORDER BY THREAD#, SEQUENCE# DESC;
-- 统计每小时日志切换次数(评估日志大小是否合理)
SELECT TO_CHAR(FIRST_TIME, 'YYYY-MM-DD HH24') AS HOUR,
COUNT(*) AS SWITCH_COUNT
FROM V$LOG_HISTORY
WHERE FIRST_TIME > SYSDATE - 1
GROUP BY TO_CHAR(FIRST_TIME, 'YYYY-MM-DD HH24')
ORDER BY 1 DESC;
三、添加日志组
sql
-- 添加一个日志组(单成员)
ALTER DATABASE ADD LOGFILE GROUP 4
('/data/oracle/redo/redo04.log') SIZE 200M;
-- 添加一个日志组(双成员,推荐)
ALTER DATABASE ADD LOGFILE GROUP 4 (
'/data/oracle/redo/redo04a.log',
'/data/oracle/redo/redo04b.log'
) SIZE 200M;
-- 不指定组号(自动分配)
ALTER DATABASE ADD LOGFILE (
'/data/oracle/redo/redo05a.log',
'/data/oracle/redo/redo05b.log'
) SIZE 200M;
-- RAC 环境:为指定线程添加日志组
ALTER DATABASE ADD LOGFILE THREAD 2 GROUP 10 (
'/data/oracle/redo/redo_t2_10a.log',
'/data/oracle/redo/redo_t2_10b.log'
) SIZE 200M;
四、添加日志成员
sql
-- 为已有日志组添加成员(镜像)
ALTER DATABASE ADD LOGFILE MEMBER
'/data/oracle/redo/redo01b.log' TO GROUP 1;
-- 同时为多个组添加成员
ALTER DATABASE ADD LOGFILE MEMBER
'/data/oracle/redo/redo01b.log' TO GROUP 1,
'/data/oracle/redo/redo02b.log' TO GROUP 2,
'/data/oracle/redo/redo03b.log' TO GROUP 3;
五、删除日志组
注意:不能删除 CURRENT 或 ACTIVE 状态的日志组,至少保留 2 个组。
sql
-- 查看状态,确认可以删除
SELECT GROUP#, STATUS FROM V$LOG;
-- STATUS: CURRENT(当前)/ ACTIVE(活跃,未归档完)/ INACTIVE(可删除)/ UNUSED(从未使用)
-- 若目标组为 ACTIVE,先强制切换并等待归档完成
ALTER SYSTEM SWITCH LOGFILE;
ALTER SYSTEM CHECKPOINT;
-- 删除日志组
ALTER DATABASE DROP LOGFILE GROUP 4;
-- 注意:以上命令只从控制文件中移除记录,物理文件需手动删除
-- OMF(Oracle Managed Files)管理的文件会自动删除
bash
# 手动删除物理文件(非 OMF)
rm -f /data/oracle/redo/redo04a.log
rm -f /data/oracle/redo/redo04b.log
六、删除日志成员
sql
-- 删除指定组的某个成员
ALTER DATABASE DROP LOGFILE MEMBER '/data/oracle/redo/redo01b.log';
-- 注意:
-- 1. 不能删除组内最后一个成员(需先删组)
-- 2. CURRENT 组的成员不能删除
-- 3. 非 OMF 文件需手动删除物理文件
bash
# 手动删除物理文件
rm -f /data/oracle/redo/redo01b.log
七、修改日志文件大小
Oracle 不支持直接修改日志文件大小,需通过"新增 + 删除"方式替换。
sql
-- 步骤1:查看当前日志组
SELECT GROUP#, BYTES/1024/1024 AS SIZE_MB, STATUS FROM V$LOG;
-- 步骤2:新增目标大小的日志组
ALTER DATABASE ADD LOGFILE GROUP 10 (
'/data/oracle/redo/redo10a.log',
'/data/oracle/redo/redo10b.log'
) SIZE 500M;
-- 步骤3:切换日志,让旧组变为 INACTIVE
ALTER SYSTEM SWITCH LOGFILE;
ALTER SYSTEM CHECKPOINT;
-- 步骤4:确认旧组状态为 INACTIVE 后删除
SELECT GROUP#, STATUS FROM V$LOG;
ALTER DATABASE DROP LOGFILE GROUP 1;
-- 步骤5:删除物理文件
-- rm -f /data/oracle/redo/redo01*.log
-- 步骤6:用新路径重建该组(可选,保持组号连续)
ALTER DATABASE ADD LOGFILE GROUP 1 (
'/data/oracle/redo/redo01a.log',
'/data/oracle/redo/redo01b.log'
) SIZE 500M;
-- 重复以上步骤处理其余日志组
八、日志线程(Thread)管理
线程主要用于 RAC 环境,每个实例对应一个线程。
sql
-- 查看线程信息
SELECT THREAD#, STATUS, ENABLED, GROUPS, OPEN_TIME
FROM V$THREAD;
-- 查看各线程的日志组
SELECT GROUP#, THREAD#, SEQUENCE#, STATUS
FROM V$LOG
ORDER BY THREAD#, GROUP#;
-- 启用线程(RAC 新增实例时)
ALTER DATABASE ENABLE PUBLIC THREAD 2;
-- 禁用线程(RAC 减少实例时)
ALTER DATABASE DISABLE THREAD 2;
-- 为线程2添加日志组
ALTER DATABASE ADD LOGFILE THREAD 2 GROUP 11 (
'/data/oracle/redo/redo_t2_11a.log',
'/data/oracle/redo/redo_t2_11b.log'
) SIZE 200M;
-- 查看线程与实例对应关系(RAC)
SELECT INST_ID, THREAD#, STATUS FROM GV$THREAD ORDER BY INST_ID;
九、日志切换与检查点
sql
-- 手动切换日志
ALTER SYSTEM SWITCH LOGFILE;
-- RAC 环境切换指定线程的日志
ALTER SYSTEM SWITCH ALL LOGFILE;
-- 强制检查点(加速 ACTIVE 状态变为 INACTIVE)
ALTER SYSTEM CHECKPOINT;
-- 全局检查点(RAC)
ALTER SYSTEM CHECKPOINT GLOBAL;
十、日志损坏恢复
10.1 非 CURRENT 组损坏(INACTIVE 状态)
sql
-- 清除损坏的日志组(不影响数据)
ALTER DATABASE CLEAR LOGFILE GROUP 2;
-- 若日志组未归档,强制清除(会导致该日志无法用于恢复)
ALTER DATABASE CLEAR UNARCHIVED LOGFILE GROUP 2;
10.2 CURRENT 组损坏(最严重)
bash
# 需要不完全恢复,步骤:
# 1. 尝试正常关库
sqlplus / as sysdba
sql
SHUTDOWN ABORT;
STARTUP MOUNT;
-- 尝试强制打开(可能丢失部分数据)
ALTER DATABASE OPEN RESETLOGS;
-- 若失败,需要从备份恢复
RECOVER DATABASE UNTIL CANCEL;
ALTER DATABASE OPEN RESETLOGS;
10.3 日志成员损坏(组内其他成员正常)
sql
-- 删除损坏成员,重新添加
ALTER DATABASE DROP LOGFILE MEMBER '/data/oracle/redo/redo01b.log';
ALTER DATABASE ADD LOGFILE MEMBER '/data/oracle/redo/redo01b.log' TO GROUP 1;
-- Oracle 会自动从同组其他成员同步内容
十一、最佳实践
| 项目 | 建议 |
|---|---|
| 日志组数量 | 至少 3 组,繁忙系统 4-6 组 |
| 每组成员数 | 2 个,分布在不同磁盘/控制器 |
| 日志文件大小 | 目标每 15-30 分钟切换一次,通常 200M-1G |
| 日志切换频率 | 过于频繁(<5分钟)需扩大日志;过慢(>60分钟)可适当缩小 |
| 存放位置 | 与数据文件、归档日志分开,使用独立高速磁盘 |
| RAC 环境 | 每个线程至少 3 组,组间大小保持一致 |
| 监控 | 定期检查 V$LOG 中是否有长期 ACTIVE 状态的组 |
十二、常见问题
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 无法删除日志组 | 组状态为 CURRENT 或 ACTIVE | 切换日志 + 执行检查点后再删 |
| 日志组一直 ACTIVE | 归档进程卡住或归档目录满 | 检查归档进程,清理归档空间 |
| ORA-00350: 需要归档 | 日志组未归档就要被覆盖 | 检查归档进程,增加日志组数量 |
| ORA-00312: 日志文件不可访问 | 文件损坏或路径错误 | 使用 CLEAR LOGFILE 重建 |
| 日志切换过于频繁 | 日志文件太小 | 增大日志文件 SIZE |
| 添加成员报错 ORA-00301 | 文件已存在 | 删除旧文件或换路径 |