查找oracle归档日志 产生的原因

来源:这里教程网 时间:2026-03-03 22:48:43 作者:

 归档日志暴涨通常意味着数据库中有大量的数据变更(INSERT, UPDATE, DELETE)。

需要明确一点: Oracle本身没有直接记录“某个表产生了多少归档日志”的机制。归档日志记录的是重做日志(Redo Log)的内容,而重做日志是为保证数据一致性和恢复而记录的 所有数据块变更,包括数据字典的变化等。

因此,我们需要通过一些间接但非常有效的方法来定位“元凶”。

以下是监控和定位产生大量归档日志的表或操作的完整方案:

方法一:通过AWR报告识别Top SQL和Top Segments(最常用、最有效)

AWR报告是首选工具,它能提供特定时间段内的系统快照。

    生成AWR报告

    首先确定归档日志暴涨的时间段(例如:10:00 - 12:00)。

  1. 登录到数据库服务器,使用  sqlplus / as sysdba。

  2. 生成该时间段的AWR报告:

    @$ORACLE_HOME/rdbms/admin/awrrpt.sql

    根据提示输入报告格式(html或txt)、起始和结束的快照ID。

  3. 在AWR报告中分析关键章节

    SQL Ordered by Elapsed Time / CPU Time / Gets: 这里列出了执行时间最长、消耗CPU最多、逻辑读最高的SQL。重点关注那些涉及大量数据修改的 INSERT,  UPDATE,  DELETE,  MERGE语句。

  4. SQL Ordered by Executions: 如果某条SQL虽然简单,但执行次数极高,也可能产生大量日志。

  5. Segments by Logical Reads / Physical Reads / Row Lock Waits: 这个章节至关重要!找到  “Segments by DB Block Changes” 或  “Segments by Physical Writes”。这里直接列出了数据块变更最多的段(表、索引)。排在榜首的表,就是最可疑的对象。

  6. Load Profile: 查看“Redo size per second”和“Redo size per transaction”,确认在快照期间redo的生成速率是否异常。

方法二:实时监控当前活动会话

当问题正在发生时,这种方法非常有效。

    使用  v$session 和  v$sql 视图

    SELECT s.sid,
           s.serial#,
           s.username,
           s.program,
           s.module,
           s.sql_id,
           q.sql_text,
           s.blocking_session,
           s.eventFROM   v$session s,
           v$sql qWHERE  s.sql_id = q.sql_id(+)AND    s.status = 'ACTIVE'AND    s.type <> 'BACKGROUND'AND    s.sql_id IS NOT NULL;

    观察哪些会话正在执行SQL,特别是那些 sql_text中包含大量数据操作(如批量INSERT/UPDATE)的会话。

  1. 关注  program 和  module 列,可以知道是哪个应用程序或模块发起的操作。

  2. 使用  v$active_session_history 和  v$sql(需要Oracle诊断包许可) 这个视图每秒采样一次活动会话,即使问题已经过去,只要在内存中保留着,就能回溯。

    SELECT ash.sql_id,
           sq.sql_text,
           ash.program,
           ash.module,
           ash.session_id,
           ash.sample_time,
           COUNT(*)FROM   v$active_session_history ash,
           v$sql sqWHERE  ash.sql_id = sq.sql_idAND    ash.sample_time > SYSDATE - INTERVAL '30' MINUTE -- 查询最近30分钟AND    ash.session_state = 'ON CPU' -- 或者 'WAITING'AND    ash.event IN ('db file sequential read', 'db file scattered read', 'log file sync') -- 常见与IO和日志相关的事件GROUP BY ash.sql_id, sq.sql_text, ash.program, ash.module, ash.session_id, ash.sample_timeORDER BY COUNT(*) DESC;

方法三:使用LogMiner进行深度分析(最精确但最重)

如果上述方法都无法定位,可以使用LogMiner直接分析归档日志内容。这是一个重量级操作,应在需要精确信息时使用。

    添加归档日志文件

    BEGIN
      DBMS_LOGMNR.ADD_LOGFILE(
        LOGFILENAME => '/u01/app/oracle/arch/archive_log_1.arc',
        OPTIONS => DBMS_LOGMNR.NEW);
      DBMS_LOGMNR.ADD_LOGFILE(
        LOGFILENAME => '/u01/app/oracle/arch/archive_log_2.arc');END;/
  1. 启动LogMiner

    BEGIN
      DBMS_LOGMNR.START_LOGMNR(
        OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);END;/
  2. 查询  v$logmnr_contents 视图

    SELECT seg_owner,
           seg_name,
           operation,
           sql_redo,
           COUNT(*)FROM   v$logmnr_contentsWHERE  seg_name IS NOT NULL -- 只关心对段的操作AND    operation IN ('INSERT','UPDATE','DELETE','DDL')GROUP BY seg_owner, seg_name, operation, sql_redoORDER BY COUNT(*) DESC;

    seg_owner 和  seg_name 会直接告诉你哪个表被操作了多少次。

  3. 警告: 查询  v$logmnr_contents 可能会返回海量数据,请务必在测试环境练习或只分析少量归档日志。

方法四:监控表空间/段的空间使用变化

虽然不直接关联归档日志,但可以辅助判断。

SELECT owner,
       segment_name,
       segment_type,
       tablespace_name,
       bytes/1024/1024 size_mbFROM   dba_segmentsWHERE  segment_name = 'YOUR_TABLE_NAME'; -- 替换为可疑的表名

定期运行此查询,观察某个表的 size_mb是否在归档日志暴涨期间也快速增长。

总结与行动步骤

    立即响应: 如果问题正在发生,使用方法二(实时监控会话)快速定位当前活跃的罪魁祸首。

  1. 事后分析: 绝大多数情况下,使用方法一(分析AWR报告)是最佳选择。重点关注  “Segments by DB Block Changes”

  2. 深度取证: 如果AWR报告无法满足需求,或者需要极其精确的信息(例如,法律取证),再考虑使用方法三(LogMiner)。

  3. 常见原因

    批量作业: 夜间跑的ETL任务、数据归档任务、报表计算任务。

  4. 无索引的DML: 全表更新或删除。

  5. 索引维护: 重建大表的索引会产生大量redo。

  6. LOB操作: 频繁更新 CLOB或 BLOB字段。

  7. 高并发事务: 应用设计问题,导致大量小事务的提交。

找到产生大量日志的表或SQL后,解决方案就更有针对性了,例如:优化SQL、调整批量提交的间隔、在维护窗口执行大操作、使用 NOLOGGING选项(需谨慎,影响可恢复性)等。

相关推荐