归档日志暴增主因是高频DML操作导致大量redo生成,应重点分析AWR中“SQL by Rows Processed”和“SQL by Executions”,结合DBA_HIST_ACTIVE_SESS_HISTORY、V$SESS_IO与V$TRANSACTION实时验证,并检查索引缺失、无条件更新等根因。
归档日志暴增,先看 AWR 里哪类 SQL 在“狂写”
归档日志生成快,本质是数据库在频繁做 commit 或产生大量重做(redo),而 awr 报告里的 sql ordered by gets 或 sql ordered by executions 并不能直接反映这个问题——真正该盯的是 sql ordered by physical reads 和更关键的 sql ordered by executions 结合 sql ordered by rows processed。大量 dml 的典型特征是:单条语句执行次数高、返回/影响行数巨大、且常伴随高 redo size。
实操建议:
- 生成最近 1 小时或业务高峰段的 AWR 报告(用
awrrpt.sql或 OEM),重点翻到 “SQL Statistics” 部分 - 优先筛选
Rows Processed> 10000 且Executions> 100 的语句;这类往往是批量INSERT/UPDATE脚本或 ETL 任务 - 注意
Buffer Gets和Physical Reads比值异常高的语句——可能在反复全表扫描 + 更新,导致 redo 指数级增长 - 别只看 Top SQL 列表,点开每条语句的 “SQL ID” 查它的
PLAN_HASH_VALUE,确认是否走了索引更新;全表扫描更新一行也可能产生 MB 级 redo
查不到 DML?试试从 DBA_HIST_ACTIVE_SESS_HISTORY 反向捞
有些 DML 是短连接、不走共享池缓存(比如某些 JDBC 批量插入启用了 rewriteBatchedStatements=true 但未绑定变量),AWR 的 SQL 统计会漏掉它们。这时得绕过 SQL_ID,直接从活动会话历史里挖操作类型和对象。
实操建议:
- 运行查询:
SELECT sql_opname, current_obj#, object_name, COUNT(*) cnt FROM dba_hist_active_sess_history a JOIN dba_objects o ON a.current_obj# = o.object_id WHERE sample_time > SYSDATE - 1/24 AND sql_opname IN ('INSERT', 'UPDATE', 'DELETE') AND o.owner NOT IN ('SYS', 'SYSTEM') GROUP BY sql_opname, current_obj#, object_name ORDER BY cnt DESC; - 重点关注
current_obj#非 0 且object_name是业务表名的结果;sql_opname为UPDATE但cnt极高,大概率是无 WHERE 条件或条件失效的更新 - 若
current_obj#为 0,说明操作对象不在数据字典缓存中(如临时表、全局临时表或刚创建的表),需结合应用日志或监听 trace 进一步定位
确认是 DML 导致?用 V$SESS_IO 和 V$TRANSACTION 对比验证
AWR 是聚合视图,存在采样延迟和统计归并;要快速验证当前实例是否正被某会话“狂刷”归档,得看实时内存视图。核心逻辑是:高 DML 会同时推高会话的 BLOCK_CHANGES(重做块变更数)和事务的 USED_UBLK(回滚块使用量),二者应呈强相关。
实操建议:
- 执行:
SELECT s.sid, s.serial#, s.username, s.program, i.block_changes, t.used_ublk, t.start_time FROM v$session s JOIN v$sess_io i ON s.sid = i.sid LEFT JOIN v$transaction t ON s.taddr = t.addr WHERE i.block_changes > 10000 ORDER BY i.block_changes DESC; -
block_changes> 10000 是一个经验阈值;超过即表明该会话近期产生了大量重做,再结合t.used_ublk是否同步增长,能排除纯物理读误报 - 如果
t.used_ublk为 NULL,但block_changes很高,可能是NOLOGGING操作(如直通路径插入),此时归档不会增加,但需警惕备份一致性风险 - 查出 SID 后,立刻用
ALTER SYSTEM KILL SESSION '<code>sid,serial#' IMMEDIATE 中止可疑会话(仅限测试/紧急场景)
归档生成速率本身怎么看?别只盯 v$archived_log
v$archived_log 记录的是归档完成事件,滞后于实际 redo 产生;真正衡量“生成快”的指标,是单位时间内的 redo 量,应直接查 v$sysstat 中的 redo size 增量。
实操建议:
- 运行两次快照对比:
SELECT name, value FROM v$sysstat WHERE name = 'redo size'; -- 记下 value1
等 60 秒后再次执行,得 value2;差值除以 60 ≈ 每秒 redo 字节数 - 若结果持续 > 5MB/s,基本可判定存在异常 DML;> 20MB/s 通常意味着批量作业失控或循环更新
- 注意
v$sysstat的redo size包含所有重做(包括系统自身操作),所以要结合前面的会话级分析交叉印证,避免把 RMAN 备份或 Data Guard 日志传输误判为业务 DML - 如果数据库启用了
FORCE LOGGING,即使 DML 加了NOLOGGING,也会强制记 redo——此时归档增速会比预期更高,排查时得先查SELECT force_logging FROM v$database
归档日志生成快这件事,表面看是磁盘写得多,根子往往卡在一条没加索引的 UPDATE 条件、一个没设批大小的 Java for 循环、或者一个忘了加 WHERE 的 DELETE。AWR 是线索,不是结论;真正要动手的,永远是那几行 SQL 和它背后的数据分布。


















