暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

Oracle的诊断事件及其应用

白鳝的洞穴 2020-04-26
1352
接触Oracle三五年后,有一段时间对诊断事件特别着迷。在一些国外的论坛上看到高手们通过诊断事件进行问题分析或者解决某个特定问题,都觉得特别的酷。有一段时间甚至迷上了诊断事件,认认真真的研究了几个月时间。那时候觉得诊断事件就是DBA的屠龙宝刀,不过屠龙术学会了,发现其实身边没有啥龙给你屠。如果真的有龙,那也是保护动物,岂是你等小儿可以屠的。从业这么多年,通过使用诊断事件去解决的问题虽然有,但是十分少。不过有些诊断事件还是经常会用到的,我觉得一个DBA不必要刻意花大精力去学习诊断事件,初步了解,需要时能用就可以了。
诊断事件的主要用途不外乎两种:一是在分析问题的时候获得更多的信息

;第二是通过设置诊断事件解决系统问题,修改Oracle的运行特性或者启用某些内部功能。要注意的是诊断事件一般无正式文档支持,在使用时要十分小心。如果你对某个诊断事件不甚了解,那么在使用之前最好咨询下使用过的人或者找专家咨询一下。诊断事件的使用一般有几个场景:

  1. 根据需要DUMP数据用于分析

  2. 当某个ORA错误发生时产生DUMP

  3. 修改数据库运行特性

  4. 在数据库运行的时候获取额外的TRACE信息

第一种情况最常见的使用就是DUMP一个数据块来分析问题。可能很多DBA在学习Oracle的时候都DUMP过数据块来学习Oracle的内部数据存储结构,不过很少在实战中使用到这个功能。实际上这个功能是老白在实际生产环境用的最多的。当数据库出现坏块的时候,要看看坏块到底是怎么回事,就需要DUMP数据块,遇到ORA-600 [KCBxxx]错误的时候,也往往会把出错的数据块DUMP出来看看。另外一种情况经常用到的是确认表中的碎片比较严重,或者分析一张表中数据量很小,但是全表扫描消耗很多buffer get的情况。这种情况可以通过下面的命令来设置会话级的诊断事件:

alter session set events 'immediate trace name <dump> level <n>'

比如下面的命令可以按10级DUMP出控制文件的信息:

alter session set events 'immediate   trace name controlf level 10';

第二种场景也偶尔会用到,当我们发现alert log或者用户会话报了某个ORA错误,但是我们缺乏相关的TRACE来做定位分析的时候,可以设置当某个错误号发生时产生TRACE文件,记录当时的场景。比如你想分析登录失败的一些详细情况(在Oracle 8i时代甚至被用来做登录错误的审计)或者分析主键冲突操作的一些详情,我们都可以设置诊断事件来获得更为详细的信息。不过对于负载较高的系统我们一定要注意,这种事件设置后,采样到足够数据后一定要关闭,否则可能会把你的文件系统撑爆。对于集中报错十分频繁的系统,设置此类DUMP也要十分谨慎,谨防导致灾难性后果。这类诊断事件一般在参数文件中设置:

event = "<error> trace name errorstack level <n>"

比如下面的设置会在死锁(ORA-60)产生时,进行1级DUMP

event = "60 trace name errorstack level 1"

第三种场景是修改数据块运行的特性,最常见的用法是用于规避某个bug,Oracle的某些BUG暂时无法解决,可以通过关闭某些数据库特性来规避,这种情况,有时候可以通过设置某些参数来完成,有时候就只能通过设置某个诊断事件来解决了。此类诊断事件一般写在参数文件里:

event = "<event> trace name context forever,  level <level>"

第四种是数据库运行时获得更多的TRACE信息,最著名的就是10046事件和10053事件了。10046可以跟踪SQL执行的过程,记录SQL执行过程中的一些详细的信息,通过tkprof工具可以生成相关的报告10053可以了解一条SQL的执行计划是如何确定的。此类诊断事件可以写在参数文件里:

event = "<event> trace name context forever,       level <level>"

也可以直接在SQL*PLUS中用SQL语句设定。

alter {session|system} set events'<event> trace name context forever, level <n>';

诊断事件设置的方法有5种:

1、参数文件:

event = "<event name> <action>    {:<event name> <action>}*"

2、当前会话:

alter session set events       '<event name> <action>     {:<event name> <action>}*'

3、所有新会话:

alter system set events     '<event name> <action>      {:<event name> <action>}*'

4、设置其他会话的事件:

sys.dbms_system.set_ev(sid,serial#,<event>,<level>,'<action>')

5、使用ORADEBUG:

oradebug <command>

如果我们要同时设置多个等待事件,在参数文件中,有两种方法:

event = "10015 trace name context forever" 

event = "10046 trace name context forever, level 4"

或者:

event = "10015 trace name context forever: 10046 trace name context forever, level 4"

要注意的是,中间的分隔符是":",而不是Oracle常用的“;”。而如果我们要在同一个诊断事件中设置多个活动,那么我们就需要用";"来分隔了:
event = "4031 trace name   HEAPDUMP level 1 ;     name ERRORSTACK level 3"

最后要说一点,诊断事件的使用一定要慎重,如果你不了解它就去使用,那么可能会捅大篓子的。

最后修改时间:2020-04-27 08:10:50
文章转载自白鳝的洞穴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论