阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Oracle 11g R2性能优化 SQL TRACE

211次阅读
没有评论

共计 7191 个字符,预计需要花费 18 分钟才能阅读完成。

目录

  • 环境准备
  • 跟踪方式
    • 当前会话跟踪
    • 其他会话跟踪
    • DBMS_MONITOR 包跟踪
    • 当前数据库跟踪
    • 采用登录触发器跟踪
  • 总结
  • 参考

正文

作为 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

更多 Oracle 相关信息见Oracle 专题页面 https://www.linuxidc.com/topicnews.aspx?tid=12

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计7191字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中