zoukankan      html  css  js  c++  java
  • Oracle 11g R2性能优化 SQL TRACE

    作为Oracle官方自带的一种基本性能诊断工具,SQL Trace可以用来评估当前正在运行的SQL语句的效率,同时为该语句生成统计信息等,并保存这些信息到指定路径下的跟踪文件(trace)当中。SQL Trace会将一条SQL语句或者PL/SQL包执行过程全部输出到跟踪文件(trace)当中,可以通过分析跟踪文件(trace)来分析SQL语句的执行效率并进行性能诊断与优化。

    通常来说trace文件的内容不易于理解与阅读,Oracle官方还提供了工具tkprof对trace文件进行格式化处理,本文不讨论tkprof工具的使用。之前在工作中也有使用过SQL Trace进行SQL语句的跟踪诊断,但都没有进行完整的总结,本文就SQL Trace工具的使用进行梳理。

    环境准备

    1. 操作系统(OS):CentOS Linux release 7.5.1804 (Core)
    2. 数据库版本(Oracle Database):Oracle Database 11g R2(11.2.0.4.0)

    同时配置了示例SCHEMA和解锁了用户SCOTTHR

    跟踪方式

    开启SQL Trace有如下几种场景与方式:

    1. 当前会话开启跟踪本会话;
    2. 当前会话开启跟踪其他会话;
    3. 使用DBMS_MONITOR包来开启跟踪;
    4. 根据登录触发器来开启跟踪。

    当前会话跟踪

    最简单的方法是在SQL*PLUS当中执行如下语句:

    • 开启:
    -- 配置trace文件的标识符便于寻找定位
    SYS@dbabd> alter session set tracefile_identifier = dbabd;
    
    -- 开启当前会话跟踪
    SYS@dbabd> alter session set sql_trace = true;
    

    通过运行以上语句就开启了当前会话的跟踪,trace文件位于 $ORACLE_BASE/diag/rdbms/dbabd/dbabd/trace目录下:

    $ pwd
    /data/app/oracle/diag/rdbms/dbabd/dbabd/trace
    $ ls *DBABD*
    dbabd_ora_27978_DBABD.trc  dbabd_ora_27978_DBABD.trm
    

    以上得到trace文件当中并不包含绑定变量值,也不包含等待事件信息,如果需要这些信息,可以使用DBMS_SESSION包来开启跟踪,前提是用户必须有ALTER SESSION权限,否则会报ORA-01031: insufficient privileges错误。关于DBMS_SESSION包的用法可以参考官方文档:DBMS_SESSION

    如果事先没有配置trace文件的标识符,则可以通过以下语句进行定位:

    • 定位:
    -- 语句
    select tracefile
      from v$session s
      join v$process p
        on p.addr = s.paddr
     where s.audsid = USERENV('SESSIONID');
    
    -- 结果
    SYS@dbabd> select tracefile
      2    from v$session s
      3    join v$process p
      4      on p.addr = s.paddr
      5   where s.audsid = USERENV('SESSIONID');
    
    TRACEFILE
    ----------------------------------------------------------------------------------------------------
    /data/app/oracle/diag/rdbms/dbabd/dbabd/trace/dbabd_ora_27978_DBABD.trc
    

    有时需要确认当前会话是否开启了跟踪,可以使用如下语句查询:

    • 查询:
    -- 语句
    select s.sql_trace,
           s.sql_trace_waits,
           s.sql_trace_binds,
           traceid,
           tracefile
      from v$session s
      join v$process p
        on p.addr = s.paddr
     where s.audsid = USERENV('SESSIONID');
    
    -- 结果
    SYS@dbabd> select s.sql_trace,
      2         s.sql_trace_waits,
      3         s.sql_trace_binds,
      4         traceid,
      5         tracefile
      6    from v$session s
      7    join v$process p
      8      on p.addr = s.paddr
      9   where s.audsid = USERENV('SESSIONID');
    
    SQL_TRACE  SQL_TRACE_WAITS SQL_TRACE_BINDS TRACEID    TRACEFILE
    ---------- --------------- --------------- ---------- ------------------------------------------------------------
    ENABLED   FALSE           FALSE           DBABD      /data/app/oracle/diag/rdbms/dbabd/dbabd/trace/dbabd_ora_2797
                                                          8_DBABD.trc
    

    如果需要关闭当前会话跟踪,则执行如下语句:

    • 关闭
    SYS@dbabd> alter session set sql_trace = false;
    

    其他会话跟踪

    如果是通过当前会话开启对其他会话的跟踪,一般都由DBA通过SYS用户操作,可以使用DBMS_SYSTEM包当中一个存储过程SET_SQL_TRACE_IN_SESSION,前提是需要获取到会话的SIDSERIAL#

    • 查看DBMS_SYSTEM包当中的结构
    SYS@dbabd> desc dbms_system
    
    …………省略…………
    
    PROCEDURE SET_EV
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     SI                             BINARY_INTEGER          IN
     SE                             BINARY_INTEGER          IN
     EV                             BINARY_INTEGER          IN
     LE                             BINARY_INTEGER          IN
     NM                             VARCHAR2                IN
    
    …………省略…………
    
    PROCEDURE SET_SQL_TRACE_IN_SESSION
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     SID                            NUMBER                  IN
     SERIAL#                        NUMBER                  IN
     SQL_TRACE                      BOOLEAN                 IN
    
    • 获取其他会话的SIDSERIAL#
    SYS@dbabd> select sid,SERIAL#,username from v$session where username is not null;
    
           SID    SERIAL# USERNAME
    ---------- ---------- ------------------------------------------------------------------------------------------
           125         17 SYS
           141         45 SCOTT
    

    实际环境当中可能出现同一个用户有多个会话存在,需要根据v$session视图当中的其他选项进行判断,这里假设只有一个SCOTT用户会话。

    • 开启对SCOTT用户会话的跟踪
    SYS@dbabd> begin
      2    dbms_system.SET_SQL_TRACE_IN_SESSION(SID => 141,
      3                                         SERIAL# => 45,
      4                                         SQL_TRACE => true
      5    );
      6  end;
      7  /
    
    PL/SQL procedure successfully completed.
    
    或
    
    SYS@dbabd> exec dbms_system.SET_SQL_TRACE_IN_SESSION(141,45,true);
    
    PL/SQL procedure successfully completed.
    
    • 定位跟踪的trace文件
    SYS@dbabd> select s.sql_trace,
      2         s.sql_trace_waits,
      3         s.sql_trace_binds,
      4         traceid,
      5         tracefile
      6    from v$session s
      7    join v$process p
      8      on p.addr = s.paddr
      9   where s.sid = 141;
    
    SQL_TRACE  SQL_TRACE_WAITS SQL_TRACE_BINDS TRACEID    TRACEFILE
    ---------- --------------- --------------- ---------- ------------------------------------------------------------
    ENABLED    FALSE           FALSE           SCOTT      /data/app/oracle/diag/rdbms/dbabd/dbabd/trace/dbabd_ora_1014
                                                          _SCOTT.trc
    
    • 关闭对SCOTT用户会话的跟踪
    SYS@dbabd> exec dbms_system.SET_SQL_TRACE_IN_SESSION(141,45,false);
    
    PL/SQL procedure successfully completed.
    

    DBMS_MONITOR包跟踪

    无论是跟踪当前会话或者其他会话都可以采用DBMS_MONITOR包当中的SESSION_TRACE_ENABLE存储过程。跟踪其他会话的前提还是需要获取到会话的SIDSERIAL#,关闭则使用包当中的SESSION_TRACE_DISABLE存储过程。

    存储过程SESSION_TRACE_ENABLE参数需求如下,详细可参考官方文档:SESSION_TRACE_ENABLE Procedure

    PROCEDURE SESSION_TRACE_ENABLE
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     SESSION_ID                     BINARY_INTEGER          IN     DEFAULT    -- 对应SID
     SERIAL_NUM                     BINARY_INTEGER          IN     DEFAULT    -- 对应SERIAL#
     WAITS                          BOOLEAN                 IN     DEFAULT    -- 对应是否加入等待事件跟踪
     BINDS                          BOOLEAN                 IN     DEFAULT    -- 对应是否加入绑定变量跟踪
     PLAN_STAT                      VARCHAR2                IN     DEFAULT    -- 对应跟踪转储行数据频率,取值参考官方文档
    

    存储过程SESSION_TRACE_DISABLE参数需求如下,详细可参考官方文档:SESSION_TRACE_DISABLE Procedure

    PROCEDURE SESSION_TRACE_DISABLE
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     SESSION_ID                     BINARY_INTEGER          IN     DEFAULT
     SERIAL_NUM                     BINARY_INTEGER          IN     DEFAULT
    

    从以上两个存储过程所需参数来看,如果是跟踪当前会话的话可以省略SESSION_IDSERIAL_NUM这两个参数,具体的开启和关闭语句可以参考其他会话跟踪当中的DBMS_SYSTEM包使用方法。

    当前数据库跟踪

    使用DBMS_MONITOR包还可以用来开启整个数据库的跟踪,但是这会造成trace文件异常庞大,不便于定位具体问题,而且也会造成一定的性能损失,所以通常不建议开启。

    采用SQL语句方式:

    -- 开启
    SYS@dbabd> alter system set sql_trace = true;
    
    -- 关闭
    SYS@dbabd> alter system set sql_trace = false;
    

    采用DBMS_MONITOR包方式,主要使用DATABASE_TRACE_ENABLEDATABASE_TRACE_DISABLE两个存储过程:

    PROCEDURE DATABASE_TRACE_ENABLE
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     WAITS                          BOOLEAN                 IN     DEFAULT
     BINDS                          BOOLEAN                 IN     DEFAULT
     INSTANCE_NAME                  VARCHAR2                IN     DEFAULT
     PLAN_STAT                      VARCHAR2                IN     DEFAULT
    PROCEDURE DATABASE_TRACE_DISABLE
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     INSTANCE_NAME                  VARCHAR2                IN     DEFAULT
    
    -- 开启
    SYS@dbabd> exec dbms_monitor.DATABASE_TRACE_ENABLE(true,true,'dbabd','all_executions');
    
    -- 关闭
    SYS@dbabd> exec dbms_monitor.DATABASE_TRACE_DISABLE('dbabd');
    

    采用登录触发器跟踪

    可以通过创建登录触发器来跟踪某个用户的SQL执行效率情况,登录触发器会在会话初始化的时候去执行,触发器可以根据指定条件是否对这次会话开启跟踪,以下登录触发器是以SCOTT用户为例,为SCOTT用户登录的所有会话设置合适的trace文件标识符并开启跟踪。

    -- 创建触发器SCOTT_LOGIN_TRACE语句
    create or replace trigger scott_login_trace
    	after logon on database 
    begin
    	if user = 'SCOTT'
    	then
    		execute immediate 'alter session set tracefile_identifier = SCOTT';
    		dbms_session.session_trace_enable(waits => true, binds => true, plan_stat => 'all_executions');
    	end if;
    end;
    /
    

    使用SYS用户进行创建:

    SYS@dbabd> create or replace trigger scott_login_trace
      2  after logon on database
      3  begin
      4  if user = 'SCOTT'
      5  then
      6  execute immediate 'alter session set tracefile_identifier = SCOTT';
      7  dbms_session.session_trace_enable(waits => true,
      8                                    binds => true,
      9                                    plan_stat => 'all_executions'
     10  );
     11  end if;
     12  end;
     13  /
    
    Trigger created.
    
    

    查看触发器状态:

    SYS@dbabd> select owner,trigger_name,status,trigger_body from all_triggers where owner = 'SYS' and trigger_name = 'SCOTT_LOGIN_TRACE';
    
    OWNER      TRIGGER_NAME         STATUS     TRIGGER_BODY
    ---------- -------------------- ---------- --------------------------------------------------------------------------------
    SYS        SCOTT_LOGIN_TRACE    ENABLED    begin
                                               if user = 'SCOTT'
                                               then
                                               execute immediate 'alter session set tracefile_identifier = SCOTT';
                                               dbms_session.session_trace_enable(waits => true, binds => true, plan_stat => 'all_executions');
                                               end if;
                                               end;
    
    

    创建完触发器之后,SCOTT用户只要一登录就会默认开启跟踪。

    总结

    以上梳理了常见的开启SQL TRACE的几种方式,但是原始的trace文件可读性比较差,通常不会直接去读取,而是通过工具tkprof进行格式化之后进行阅读,关于tkprof的使用可以参考我另一篇博文:Oracle 11g R2性能优化 tkprof

    参考

    https://docs.oracle.com/cd/E11882_01/server.112/e41573/sqltrace.htm#PFGRF010
    https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_sessio.htm#ARPLS054
    https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_monitor.htm#ARPLS091

    ☆〖本人水平有限,文中如有错误还请留言批评指正!〗☆

  • 相关阅读:
    jvm的概述
    关于请求中的一些小知识点
    对react项目进行进一步的修饰
    java基于token进行登录超时检验和有效性校验
    react获取文本框的值
    redis数据库的缓存击穿和缓存穿透
    centos克隆虚拟机
    Java中的第三大特性-多态性
    java中String类的使用
    Maven更换阿里源与仓库地址
  • 原文地址:https://www.cnblogs.com/dbabd/p/10282006.html
Copyright © 2011-2022 走看看