首页 > 数据库 > Oracle > 查找oracle归档日志 产生的原因
归档日志暴涨通常意味着数据库中有大量的数据变更(INSERT, UPDATE, DELETE)。
需要明确一点: Oracle本身没有直接记录“某个表产生了多少归档日志”的机制。归档日志记录的是重做日志(Redo Log)的内容,而重做日志是为保证数据一致性和恢复而记录的 所有数据块变更,包括数据字典的变化等。
因此,我们需要通过一些间接但非常有效的方法来定位“元凶”。
以下是监控和定位产生大量归档日志的表或操作的完整方案:
AWR报告是首选工具,它能提供特定时间段内的系统快照。
生成AWR报告
首先确定归档日志暴涨的时间段(例如:10:00 - 12:00)。
登录到数据库服务器,使用
sqlplus / as sysdba。
生成该时间段的AWR报告:
@$ORACLE_HOME/rdbms/admin/awrrpt.sql
根据提示输入报告格式(html或txt)、起始和结束的快照ID。
在AWR报告中分析关键章节
SQL Ordered by Elapsed Time / CPU Time / Gets: 这里列出了执行时间最长、消耗CPU最多、逻辑读最高的SQL。重点关注那些涉及大量数据修改的
INSERT,
UPDATE,
DELETE,
MERGE语句。
SQL Ordered by Executions: 如果某条SQL虽然简单,但执行次数极高,也可能产生大量日志。
Segments by Logical Reads / Physical Reads / Row Lock Waits: 这个章节至关重要!找到 “Segments by DB Block Changes” 或 “Segments by Physical Writes”。这里直接列出了数据块变更最多的段(表、索引)。排在榜首的表,就是最可疑的对象。
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)的会话。
关注
program 和
module 列,可以知道是哪个应用程序或模块发起的操作。
使用
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直接分析归档日志内容。这是一个重量级操作,应在需要精确信息时使用。
添加归档日志文件
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;/
启动LogMiner
BEGIN DBMS_LOGMNR.START_LOGMNR( OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);END;/
查询
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 会直接告诉你哪个表被操作了多少次。
警告: 查询
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是否在归档日志暴涨期间也快速增长。
立即响应: 如果问题正在发生,使用方法二(实时监控会话)快速定位当前活跃的罪魁祸首。
事后分析: 绝大多数情况下,使用方法一(分析AWR报告)是最佳选择。重点关注 “Segments by DB Block Changes”。
深度取证: 如果AWR报告无法满足需求,或者需要极其精确的信息(例如,法律取证),再考虑使用方法三(LogMiner)。
常见原因:
批量作业: 夜间跑的ETL任务、数据归档任务、报表计算任务。
无索引的DML: 全表更新或删除。
索引维护: 重建大表的索引会产生大量redo。
LOB操作: 频繁更新
CLOB或
BLOB字段。
高并发事务: 应用设计问题,导致大量小事务的提交。
找到产生大量日志的表或SQL后,解决方案就更有针对性了,例如:优化SQL、调整批量提交的间隔、在维护窗口执行大操作、使用
NOLOGGING选项(需谨慎,影响可恢复性)等。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10201716/viewspace-3099592/ ,如需转载,请注明出处,否则将追究法律责任。