Oracle Redo 日志操作手册

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 文件已存在 删除旧文件或换路径
相关推荐
攒了一袋星辰2 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql
W.D.小糊涂2 小时前
gpu服务器安装windows+ubuntu24.04双系统
c语言·开发语言·数据库
云贝教育-郑老师2 小时前
【OceanBase 的多租户架构是怎样的?有什么优势?】
数据库·oceanbase
顶点多余3 小时前
使用C/C++语言链接Mysql详解
数据库·c++·mysql
xiaokangzhe3 小时前
MySQL 数据库操作
数据库·oracle
发际线还在4 小时前
互联网大厂Java三轮面试全流程实战问答与解析
java·数据库·分布式·面试·并发·系统设计·大厂
小王不爱笑1324 小时前
MyBatis 执行流程源码级深度解析:从 Mapper 接口到 SQL 执行的全链路逻辑
数据库·sql·mybatis
山峰哥5 小时前
SQL优化实战:从索引策略到执行计划的极致突破
数据库·sql·性能优化·编辑器·深度优先
总要冲动一次5 小时前
离线安装 percona-xtrabackup-24
linux·数据库·mysql·centos