`

如何定位那些SQL产生了大量的redo日志

 
阅读更多

在ORACLE数据库的管理、维护过程中,偶尔会遇到归档日志暴增的情况,也就是说一些SQL语句产生了大量的redo log,那么如何跟踪、定位哪些SQL语句生成了大量的redo log日志呢? 下面这篇文章结合实际案例和官方文档How to identify the causes of High Redo Generation (文档 ID 2265722.1)来实验验证一下。

 

 

首先,我们需要定位、判断那个时间段的日志突然暴增了,注意,有些时间段生成了大量的redo log是正常业务行为,有可能每天这个时间段都有大量归档日志生成,例如,有大量作业在这个时间段集中运行。  而要分析突然、异常的大量redo log生成情况,就必须有数据分析对比,找到redo log大量产生的时间段,缩小分析的范围是第一步。合理的缩小范围能够方便快速准确定位问题SQL。下面SQL语句分别统计了redo log的切换次数的相关数据指标。这个可以间接判断那个时间段产生了大量归档日志。

 

/******统计每天redo log的切换次数汇总,以及与平均次数的对比*****/
WITH T AS 
(
    SELECT TO_CHAR(FIRST_TIME, 'YYYY-MM-DD')    AS LOG_GEN_DAY, 
           TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'YYYY-MM-DD'), 
                       TO_CHAR(FIRST_TIME, 'YYYY-MM-DD'), 1, 0))
                , '999') AS "LOG_SWITCH_NUM" 
    FROM   V$LOG_HISTORY 
  WHERE FIRST_TIME < TRUNC(SYSDATE)  --排除当前这一天
    GROUP  BY TO_CHAR(FIRST_TIME, 'YYYY-MM-DD') 
)
SELECT  T.LOG_GEN_DAY
          , T.LOG_SWITCH_NUM
          , M.AVG_LOG_SWITCH_NUM
      , (T.LOG_SWITCH_NUM-M.AVG_LOG_SWITCH_NUM) AS DIFF_SWITCH_NUM
FROM  T CROSS JOIN 
(
    SELECT  TO_CHAR(AVG(T.LOG_SWITCH_NUM),'999') AS AVG_LOG_SWITCH_NUM
    FROM T
) M
ORDER BY T.LOG_GEN_DAY DESC;

 

 

SELECT    TO_CHAR(FIRST_TIME,'YYYY-MM-DD') DAY,
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'00',1,0)),'999') "00",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'01',1,0)),'999') "01",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'02',1,0)),'999') "02",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'03',1,0)),'999') "03",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'04',1,0)),'999') "04",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'05',1,0)),'999') "05",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'06',1,0)),'999') "06",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'07',1,0)),'999') "07",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'08',1,0)),'999') "08",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'09',1,0)),'999') "09",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'10',1,0)),'999') "10",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'11',1,0)),'999') "11",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'12',1,0)),'999') "12",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'13',1,0)),'999') "13",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'14',1,0)),'999') "14",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'15',1,0)),'999') "15",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'16',1,0)),'999') "16",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'17',1,0)),'999') "17",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'18',1,0)),'999') "18",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'19',1,0)),'999') "19",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'20',1,0)),'999') "20",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'21',1,0)),'999') "21",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'22',1,0)),'999') "22",
                TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME,'HH24'),'23',1,0)),'999') "23"
FROM V$LOG_HISTORY
GROUP BY TO_CHAR(FIRST_TIME,'YYYY-MM-DD') 
ORDER BY 1 DESC;

 

 

如下案例所示,2018-03-26日有一个归档日志暴增的情况,我们可以横向、纵向对比分析,然后判定在17点到18点这段时间出现异常,这个时间段与往常对比,生成了大量的redo log。

 

 

clip_image001

 

 

 

clip_image002

 

这里分享一个非常不错的分析redo log 历史信息的SQL

------------------------------------------------------------------------------------------------
REM Author: Riyaj Shamsudeen @OraInternals, LLC
REM         www.orainternals.com
REM
REM Functionality: This script is to print redo size rates in a RAC claster
REM **************
REM
REM Source  : AWR tables
REM
REM Exectution type: Execute from sqlplus or any other tool.
REM
REM Parameters: No parameters. Uses Last snapshot and the one prior snap
REM No implied or explicit warranty
REM
REM Please send me an email to rshamsud@orainternals.com, if you enhance this script :-)
REM  This is a open Source code and it is free to use and modify.
REM Version 1.20
REM
------------------------------------------------------------------------------------------------
 
set colsep '|'
set lines 220
alter session set nls_date_format='YYYY-MM-DD HH24:MI';
set pagesize 10000
with redo_data as (
SELECT instance_number,
       to_date(to_char(redo_date,'DD-MON-YY-HH24:MI'), 'DD-MON-YY-HH24:MI') redo_dt,
       trunc(redo_size/(1024 * 1024),2) redo_size_mb
 FROM  (
  SELECT dbid, instance_number, redo_date, redo_size , startup_time  FROM  (
    SELECT  sysst.dbid,sysst.instance_number, begin_interval_time redo_date, startup_time,
  VALUE -
    lag (VALUE) OVER
    ( PARTITION BY  sysst.dbid, sysst.instance_number, startup_time
      ORDER BY begin_interval_time ,sysst.instance_number
     ) redo_size
  FROM sys.wrh$_sysstat sysst , DBA_HIST_SNAPSHOT snaps
WHERE sysst.stat_id =
       ( SELECT stat_id FROM sys.wrh$_stat_name WHERE  stat_name='redo size' )
  AND snaps.snap_id = sysst.snap_id
  AND snaps.dbid =sysst.dbid
  AND sysst.instance_number  = snaps.instance_number
  AND snaps.begin_interval_time> sysdate-30
   ORDER BY snaps.snap_id )
  )
)
select  instance_number,  redo_dt, redo_size_mb,
    sum (redo_size_mb) over (partition by  trunc(redo_dt)) total_daily,
    trunc(sum (redo_size_mb) over (partition by  trunc(redo_dt))/24,2) hourly_rate
   from redo_Data
order by redo_dt, instance_number
/

image

 

    分析到这个阶段,我们还只获取了那个时间段归档日志异常(归档日志暴增),那么要如何定位到相关的SQL语句呢?我们可以用下面SQL来定位:在这个时间段,哪些对象有大量数据块变化情况。如下所示,这两个对象(当然,对象有可能是表或索引,这个案例中,这两个对象其实是同一个表和其主键索引)有大量的数据块修改情况。基本上我们可以判断是涉及这个对象的DML语句生成了大量的redo log, 当然有可能有些场景会比较复杂,不是那么容易定位。

 

SELECT TO_CHAR(BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24') SNAP_TIME, 
       DHSO.OBJECT_NAME, 
       SUM(DB_BLOCK_CHANGES_DELTA)                     BLOCK_CHANGED 
FROM   DBA_HIST_SEG_STAT DHSS, 
       DBA_HIST_SEG_STAT_OBJ DHSO, 
       DBA_HIST_SNAPSHOT DHS 
WHERE  DHS.SNAP_ID = DHSS.SNAP_ID 
       AND DHS.INSTANCE_NUMBER = DHSS.INSTANCE_NUMBER 
       AND DHSS.OBJ# = DHSO.OBJ# 
       AND DHSS.DATAOBJ# = DHSO.DATAOBJ# 
       AND BEGIN_INTERVAL_TIME BETWEEN TO_DATE('2018-03-26 17:00', 
                                       'YYYY-MM-DD HH24:MI') 
                                       AND 
           TO_DATE('2018-03-26 18:00', 'YYYY-MM-DD HH24:MI') 
GROUP  BY TO_CHAR(BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24'), 
          DHSO.OBJECT_NAME 
HAVING SUM(DB_BLOCK_CHANGES_DELTA) > 0 
ORDER  BY SUM(DB_BLOCK_CHANGES_DELTA) DESC;

 

clip_image003

 

 

此时,我们可以生成这个时间段的AWR报告,那些产生大量redo log的SQL一般是来自TOP Gets、TOP Execution中某个DML SQL语句或一些DML SQL语句,结合上面SQL定位到的对象和下面相关SQL语句,基本上就可以判断就是下面这两个SQL产生了大量的redo log。(第一个SQL是调用包,包里面有对这个表做大量的DELETE、INSERT操作)

 

clip_image004

 

 

如果你此时还不能完全断定,也可以使用下面SQL来辅佐判断那些SQL生成了大量的redo log。 在这个案例中, 上面AWR报告中发现的SQL语句和下面SQL捕获的SQL基本一致。那么可以进一步佐证。

 

注意,该SQL语句执行较慢,执行时需要修改相关条件:时间和具体段对象。

 

SELECT TO_CHAR(BEGIN_INTERVAL_TIME,'YYYY_MM_DD HH24') WHEN,
             DBMS_LOB.SUBSTR(SQL_TEXT,4000,1) SQL,
             DHSS.INSTANCE_NUMBER INST_ID,
             DHSS.SQL_ID,
             EXECUTIONS_DELTA EXEC_DELTA,
             ROWS_PROCESSED_DELTA ROWS_PROC_DELTA
FROM DBA_HIST_SQLSTAT DHSS,
         DBA_HIST_SNAPSHOT DHS,
         DBA_HIST_SQLTEXT DHST
WHERE UPPER(DHST.SQL_TEXT) LIKE '%<segment_name>%'  --此处用具体的段对象替换
  AND LTRIM(UPPER(DHST.SQL_TEXT)) NOT LIKE 'SELECT%'
  AND DHSS.SNAP_ID=DHS.SNAP_ID
  AND DHSS.INSTANCE_NUMBER=DHS.INSTANCE_NUMBER
  AND DHSS.SQL_ID=DHST.SQL_ID
  AND BEGIN_INTERVAL_TIME BETWEEN TO_DATE('2018-03-26 17:00','YYYY-MM-DD HH24:MI')
  AND TO_DATE('2018-03-26 18:00','YYYY-MM-DD HH24:MI')

 

其实上面分析已经基本完全定位到SQL语句,剩下的就是和开发人员或Support人员沟通、了解是正常业务逻辑变更还是异常行为。如果需要进一步挖掘深入,我们可以使用日志挖掘工具Log Miner深入分析。在此不做展开分析。 其实个人在判断分析时生成了正常时段和出现问题时段的AWR对比报告(WORKLOAD REPOSITORY COMPARE PERIOD REPORT),如下所示,其中一些信息也可以供分析、对比参考。可以为复杂场景做对比分析(因为复杂场景,仅仅通过最上面的AWR报告可能无法准确定位SQL)

 

 

clip_image005

 

clip_image006

 

 

此次截图,没有截取相关SQL,其实就是最上面分析的SQL语句,如果复杂场景下,非常有用。

 

clip_image007

 

clip_image008

 

参考至:https://www.cnblogs.com/kerrycode/p/8660931.html

如有错误,欢迎指正

邮箱:czmcj@163.com

 

分享到:
评论

相关推荐

    44 redo log buffer中的缓冲日志,到底什么时候可以写入磁盘?l.pdf

    对于Redo日志文件的管理,当MySQL不断地执行增删改操作时,会产生大量的Redo日志,这些日志需要写入日志文件。为了避免日志文件占用磁盘空间越来越大,MySQL通过以下机制解决这个问题: 1. Redo日志文件默认是写入到...

    Oracle redo 异常暴增 日志挖掘 logminer

    3. **检查SQL语句**:通过Logminer获取执行频繁或者产生大量日志的SQL语句,分析其执行计划,看是否可以优化或者调整以减少日志生成。 4. **数据库配置**:检查数据库参数,如`LOG_FILE_SIZE`、`LOG_BUFFER`等,确保...

    REDO INTERNALS AND TUNING BY REDO

    4. **优化SQL语句**:避免频繁的全表扫描和不必要的索引重建等操作,这些都会导致大量的重做日志生成。 5. **使用闪回技术**:Oracle的闪回功能可以在一定程度上替代重做日志的作用,通过闪回数据存档和闪回查询等...

    ORACLE_高效SQL分析

    - **Redo Log Buffer**:用于缓存重做日志记录,这些记录会在适当的时候被写入磁盘上的重做日志文件。 - **PGA(Program Global Area)**:这部分内存主要用于存储每个用户进程的私有数据和控制信息。 #### 二、...

    深入分析Oracle数据库日志文件.rar

    例如,通过分析redo logs,可以找出导致大量写入操作的SQL语句,进而优化查询语句或者调整索引来改善性能。 在故障排查和灾难恢复场景中,日志文件扮演着关键角色。当数据库出现错误或数据丢失时,可以通过redo ...

    Oracle logMiner

    - **LogMiner结构**:LogMiner使用V$LOGMNR_CONTENTS视图提供分析结果,它包含了从redo日志中解析出的SQL语句、事务信息和时间戳等。 2. **使用LogMiner的过程** - **启动LogMiner**:通过执行DBMS_LOGMNR包中的...

    数据库清除日志工具 速度快

    在数据库管理中,日志通常分为两种类型:重做日志(Redo Log)和回滚日志(Undo Log)。重做日志记录了所有已提交事务的改变,用于在系统崩溃时恢复数据;而回滚日志则保存了未完成事务的信息,用于回滚未提交的更改...

    如何提高sql性能

    - **SGA**:SGA是最关键的内存结构之一,它包含了多个内存区,如共享池(Shared Pool)、数据缓冲区(Data Buffer Cache)、重做日志缓冲区(Redo Log Buffer)等。这些内存区对于提高SQL性能至关重要。 - **PGA**...

    MySQL的日志基础知识及基本操作学习教程

    这个日志对于跟踪数据库活动和调试非常有用,但可能会消耗大量磁盘空间,因此在生产环境中通常不启用。查询日志的状态由`general_log`变量控制,日志文件路径由`general_log_file`指定。 3. 慢查询日志(Slow Query...

    MySQL性能优化 SQL优化方法技巧

    ### MySQL性能优化与SQL优化方法技巧 #### 一、引言 MySQL作为一款广泛使用的开源关系型数据库管理系统,其性能优化对于确保应用系统的稳定性和高效运行至关重要。通过对MySQL的优化,不仅能提升系统的响应速度,还...

    Oracle11G数据库DataGuard灾备切换方案.pdf

    MRP 进程是 DataGuard 的核心进程,负责将redo日志从主库传输到备库。可以使用以下 SQL 语句来检查 MRP 进程的状态: SELECT PROCESS FROM V$MANAGED_STANDBY WHERE PROCESS LIKE 'MRP%'; 2. 确定备库是否启用 ...

    oracle 10G 数据库SQL优化,

    2. **定位 SQL 问题**:使用 ADDM 或 Top SQL 工具找到最耗时的 SQL 语句。 3. **理解执行计划**:查看 SQL 语句的执行计划,判断是否有优化空间。 4. **索引调整**:基于执行计划和查询需求添加或修改索引。 5. **...

    MySQL中常见的几种日志

    6. **一般查询日志(General Log)**:记录所有客户端发出的查询,包括成功和失败的,对于监控和调试很有帮助,但在生产环境中通常关闭,因为它会产生大量日志,影响性能。 关于binlog的管理,可以使用以下命令: -...

    删除ORACLE归档日志

    然而,随着时间的推移,归档日志会占用大量的磁盘空间,因此定期清理不再需要的旧归档日志是必要的。本文将详细解释如何在Windows和Linux系统上使用脚本删除Oracle归档日志,并讨论相关知识点。 首先,删除Oracle...

    第15章 MySQL日志PPT

    - **作用**:错误日志记录MySQL服务器启动、运行时的错误信息和警告,有助于定位和解决问题。 - **默认行为**:MySQL启动时自动开启,记录到服务器的标准错误输出或者指定的日志文件。 4. **慢查询日志(Slow ...

    分析Oracle数据库日志文件(1) .txt

    - **性能考量**:大规模日志分析可能会消耗大量系统资源,因此在生产环境中使用时需谨慎。 #### 七、示例代码 ```sql -- 设置UTL_FILE_DIR环境变量 ALTER SYSTEM SET utl_file_dir='/data6/cyx/logmnr'; -- 启动...

    查看oracle数据库是否归档和修改归档模式

    自动归档模式通过启用数据库中的`arch`进程来实现,该进程负责将redo日志写入系统归档设备。要在Oracle数据库参数文件中设置自动归档模式,需配置以下几个参数: 1. **LOG_ARCHIVE_START** - 设置为`TRUE`表示启用...

    SQL优化34条

    在事务处理中,应及时使用`COMMIT`来提交更改,这样可以释放锁资源并减少redo日志空间的占用。例如: ```sql BEGIN INSERT INTO Employees (EmployeeID, FirstName, LastName) VALUES (1001, '张', '三'); COMMIT;...

Global site tag (gtag.js) - Google Analytics