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

Oracle诊断事件说明

Oracle蓝莲花 2021-04-15
454

1.本期文档分为两部分内容,第一部分包括死锁检测的处理思路、第二部分包括常用的dump操作


开门见山,首先来看第一部分内容的分享。

1.1对于产生死锁访问oracle的线程来讲,通常我们都建议在死锁发生时转储各种实例信息。死锁跟踪会自动转储一些有价值

  trace文件信息,方便我们定位和查找内容。

  

1.2在没有正式进入案例之前,先对10046 dump内核调用做一个简单介绍(注:我们不介绍10046功能,百度一大堆,没意义)

1.2.1 alter session set events '10046 trace name context forever, level 12';一个稍微复杂的语法结构,该

语句表示我们可以进行特定扩展sql语句消耗的跟踪,这个语法实际上揭示了KSD诊断事件语法(KSD为内核服务调试)

的一些功能,事件字符串(10046)中的第一个单词指定应该在什么时候采取某些操作

1.2.2假设一个Oracle解析函数调用ksdpec()函数,参数为10046,反过来,它可以递归地调用该事件的某个动作集,然后

   将该事件级别(12)返回给调用者。由调用方对返回的值进行操作,在10046种情况下会调用某个ksd*跟踪函数

1.2.3在事件语法中,trace是最通用的操作,用于跟踪、行为更改和Oracle转储,例如完成该操作后期的

oradebug tracefile_name操作一样。

1.2.4name指定要转储/跟踪的内容的名称。当使用trace选项通常都会有name选项。

1.2.5context定义了在事件发生时我们希望Oracle转储什么内容,还是只执行上下文特定的跟踪。

   例如,如果将context替换为errorstack就不会得到SQL跟踪输出,而是在事件10046发生时得到Oracle errorstack转储

1.2.6当然啦,我们也可以使用oradebug dumplist查找所有可能的转储命令,别着急,后面会有介绍

1.2.7除了forever选项我们还有其他选择。如果我们希望只调用操作10000次,然后自动禁用该事件,我们可以使用LIFETIME选项

alter session set events '10046 trace name context level 12, lifetime 10000';

1.2.8再比如,如果我们想要对某些事件忽略该事件,并在此之后才开始操作,我们还可以指定x occurrence选项来告诉

    Oracle不要对该事件的第x个事件进行操作,并在x个事件之后才激活,下面是语句:

alter session set events '10046 trace name context level 12, lifetime 10000, after 5000 occurrences';

1.3当对10046语法有个基本了解后,我们来看出现ORA-00600检测死锁的情况发生,应该如何分析处理:

1.3.1alter session set events '60 trace name hanganalyze level 4';这里我们使用了当ORA-60在我的会话中发生,

    时,我可以在level 4调用hanganalyze。

1.3.2那么当ORA-00600错误发生时,可能单纯一种dump信息无法支撑结果分析怎么办?

alter session set events '60 trace name hanganalyze_global ; name systemstate level 266';

每当出现ORA-00600死锁错误时,我告诉Oracle调用RAC全局挂起分析和包含短堆进程(级别256 + 10 = 266)的系统状态转储

1.3.3当然,我们对每一种转储方式实现不同的选项level级别

SQL> alter session set events '60 trace name hanganalyze_global level 4, forever; -

  > name systemstate level 266, lifetime 1; -

               > name processstate level 2, forever'

              2  /


Session altered.

1.3.4到目前为止,我已经定义了使用数字采取行动的事件。事件60(对应ORA-00060错误消息)是等待资源检测到死锁错误消息

    注意,在$ORACLE_HOME/rdbms/admin/oraus中可以看到大多数ORA-错误消息和跟踪/调试事件号。Unix平台上的msg文件

等等,如果想更多了解这些功能,需要借助oracle官方资料和mos文档去学习。

1.3.5一些数字事件还有文本别名。例如,我们还可以运行以下语句,而不是使用ORA-60作为死锁事件定义

alter session set events 'deadlock trace name hanganalyze_global';

1.3.6还有一些相对特殊的用法,例如:我们可以使用以下语句来跟踪排序操作的一些内存分配。我们使用级别29的heapdump

 (PGA+UGA+调用堆)每个排序传递(sort_run事件),并且在排序操作(sort_end事件)结束时使用。而且,我们还希望

 在排序结束时使用workareatab_dump,但只在第一次排序传递期间(因此是lifetime 1条件)

1.3.7后面会对详细的dump方法做解释,别着急。我们来看一个真实环境的死锁例子:

--以下为trace文件部分内容:

1.该trace中的警告一直从27号持续发生到月3号,后续仍然有,此trace不在体现

2.此部分我们发现大量日文件写入产生等待多大几百毫秒,首先明确LGWR进程的作用:

2.1)LGWR负责将SGA的重做日志缓冲区的内容刷新到磁盘上

2.2)刚才缓冲区高速缓存被填满了。 DBWR 必须腾出空间,必须释放刚才修改的块。在这种情

况, DBWR 开始要求 LGWR 刷新保护数据库块的重做块。 在 DBWR 写入要改变硬盘的块之前, LGWR

必须刷新和这些块相关的重做信息

2.3)当commit提交后LGWR 把所有余下的缓冲区中的重做日志条目存储到硬盘上,并且在联机重做日志文件中记录SCN

3.那么既然产生日志文件等待了,就说明该动作是在commit操作时候,并不在buffer cache change blocks期间,因为只有commit提交后,释放会话占用的

所有锁定,释放在入队列等待中被占用锁定的内容。

4.即使是运行时间较长的事务,它产生的缓冲重做日志也在提交以前已经被放到硬盘上了

5.那么我们基本可以定位,该死锁是dml操作过程后,commit动作发起,LGWR进程在写磁盘日志文件期间。


----------------------------------------------

--以下为trace文件部分内容:

基于这部分trace内容我们可以定位到死锁原因是TX锁造成的,这里我们还要明确TX锁的概念:

1)许多对Oracle不太了解的技术人员可能会以为每一个TX锁代表一条被封锁的数据行,其实不然。TX的本义是Transaction(事务),当一个事务

第一次执行数据更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE语句进行查询时,它即获得一个TX(事务)锁,直至该事务结束

(执行COMMIT或ROLLBACK操作)时,该锁才被释放。所以,一个TX锁,可以对应多个被该事务锁定的数据行(在我们用的时候多是启动一个事务,

然后SELECT… FOR UPDATE NOWAIT)。

2)在Oracle的每行数据上,都有一个标志位来表示该行数据是否被锁定。Oracle不像DB2那样,建立一个链表来维护每一行被加锁的数据,这样就大

大减小了行级锁的维护开销,也在很大程度上避免了类似DB2使用行级锁时经常发生的锁数量不够而进行锁升级的情况。数据行上的锁标志一旦被置位,

就表明该行数据被加X锁,Oracle在数据行上没有S锁

----------------------------------------------

--以下为trace文件部分内容:

...列举部分内容,详细日志请关注trace文件

--

好了,到这里我们基本可以确定死锁原因是由于多个dml操作针对同一个数据库对象导致的,有update语句有delete语句。那么我还要隐身一个概念,什么

是oracle多版本并发控制?

1.基于oracle ( multi-version read consistency)特性,一个多租户的rdbms允许多个session并发访问并修改数据库内容,那么对于锁的特征可能

有如下表现:

1.1)TX锁:修改数据的事务在执行期间会获得这种锁。

1.2)TM锁和DDL锁:在你修改一个对象的内容(对于TM锁)或对象本身(对应DDL锁)时, 这些锁可以确保对象的结构不被修改。

1.3)闩( latch) :这是Oracle的内部锁,用来协调对其共享数据结构的访问

TX本身在性能和扩展性能方面是非常健壮的,TM和DDL锁定模式尽可能的采用限制最小的模式,然后latch,本身就是轻量级,包括mutex。在oracle中有区别

其他数据库明确的好处,写不会阻塞读,更不会和其他会话发生死锁。

-------------------------------------------

2.常见的dump操作部分:

2.1通常我们需要将oracle内部结构中所包含的内容进行转储操作,以便后期根据相关trace信息完成troubleshooting,那么

以下我们来对会话层面对应的event dump trace做如下说明,例如如下语句:

alter session set events'event context immediate trace name eventname forever,level number‘;

通过第一部分讲解,我们了解到符号可以连续设置多个event事件,还可以通过连续使用alter session方式去实现,整体的

格式说明如下:

2.1.1event context:指向触发dump事件的event number,所谓事件号可以是oracle的ORA错误号码,或者oracle的内部

事件号,内部事件号从10000到10999之间这里不能和immediate关键字共同使用。

2.1.2immediate:指向关键字,当发出该命令后会立即将具体的信息内容dump到trace文件中,这个关键字一般在alter

session中使用,不能够和event number或者forever关键字共同使用。

2.1.3trace name指向具体的操作名称

2.1.4event name:指向具体的事件名称

2.1.5forever:指向事件在实例或者会话的周期内始终保持有效状态,不能够和immediate共同使用。

2.1.6level指向了时间的级别,注意:在dump errorstack不存在level级别

2.1.7level number就是具体的事件编号,一般从1开始到10结束,1表示只dump结构头部信息,10表示dump所有信息

2.2block dump trace context:

2.2.1例如alter session set events'immediate trace name blockdump level xxx';表示为dump数据块地址为xxx

的数据块。也可以这么写alter session dump datafile 1 block 10表示dump数据文件为1的第10个block

2.3dump contrilfile:

2.3.1alter session set events'immediate trace name controlf level 10’;表示dump控制文件的信息内容

2.4dump redo header

2.4.1alter session set events'immediate trace name redohdr level 1';表示dump redo header的信息内容

2.5dump contril history内容:

2.5.1alter session set events'immediate trace name loghist level 1';表示只dump最早的和最迟的日志历史信息

2.5.2level number大于或者等于2,表示2的几次方的level number内容,对应也是日志历史信息内容。

2.6dump datafile header:

2.6.1alter session set events'immediate trace name file_hdrs level 1';表示dump所有数据文件头部信息

2.7错误堆践errorstack:

2.7.1dump errorstack通常来讲oracle发生错误时前台进程将得到错误提示,但通过oerr后我们很难判断出这个错误

具体的解决方式,和说明信息,需要借助于errorstack来看oracle内部调用和结构情况,找到部分症结。

2.7.2alter session set events'060 trace name errorstack forever';表示出现ORA-00060死锁事务后dump具体的

错误堆践以及进程堆践。

2.8systemstate:

2.81.dump当前系统状态以及进程的信息,这是个宝贝,我们借助systemstate能解决很多问题,后期单独通过一个文档

以及案例描述这个宝贝的强大之处。尤其当前数据库hang死的情况。


2.9dump coalesec

2.9.1dump指定表空间的free space内容,其中level number以十六进制表示,两个高位字节表示自由区间的数目,两个

低位字节表示表空间,具体语法alter session set events'immediate trace name coalesec level xxxx';

2.10dump process

2.10.1alter session set events 'immediate trace name processsate level 10';表示dump具体进程状态信息。

2.11dump库缓存:

2.11.1alter session set events'immediate trace name library_cache level 10';

2.12dump PGA UGA SGA等内存结构

2.12.1alter session set events'immediate trace name heapdump level 1';

2.13dump数据字典缓存区内容

2.13.1alter session set events'immediate trace name row_cache level 1';

2.14dump global area 

2.14.1alter session set events'immediate trace name global_area level xx';

xx的具体范围为:1包含pga 2包含sga 4包含uga 8包含indrect memory

 

2.15dump library cache

2.15.1alter session set events'immediate trace name library_cache level xx';

    xx具体范围为:1包含library cache统计信息 2包含hash table histogram 3包含library cache object handle

4.包含heap 0的库缓存句柄结构。

2.19以下是具体的案例说明:


--首先根据Rowid 查询对应的block number 和datafile number:

注:trace文件头部信息相对简单,记录数据库版本,一些平台特定信息,如主机名和操作系统级别、数据库实例名、进程标识符等

此部分无需过多关注,我们主要来看数据块整体结构的工作原理说明

Start dump data blocks tsn: 5 file#:21 minblk 397 maxblk 397

注:tsn:所在表空间编号 file:所在数据文件编号 minblk:数据块开始的编号,maxblk数据块结束的编号


Dump of buffer cache at level 4 for pdb=3 tsn=5 rdba=88080781

注:rdba=88080781是绝对数据块地址


scn: 0x0.2aef575 seq: 0x02 flg: 0x06 tail: 0xf5750602

注:scn 数据块最后一次编辑记录的系统该编号, TAIL用于验证block的完整性的,它是由SCNBase,block type,SCN seq number组成。

数据块的最后四字节tail: 0xf5750602=scnBASE+flg+seq,如果不相等会报块损坏


frmt: 0x02 chkval: 0xef80 type: 0x06=trans data

注:frmt 数据块格式,属于哪个版本 chkval 校验写入快在设置和使用oracle检查一致性和有效性  type 定义那种类型的数据块

,这里是事务型,用来存放表和索引


注:1.事务槽,对应的事务可以查询v$transaction,xid以及uba对应的数据都与v$transaction中的响应字段相同

2.xid表示事物id,由undo的段号+槽号+槽号覆盖次数三部分组成

3.uba表示undo blockaddress 第一段是回滚数据块的地址,包括回滚段文件号和数据块号;第二段是回滚序列号;第三段是回滚记录号

4.flag:事务标志位 --代表为提交

C--- = transaction has beencommitted and locks cleaned out

-B-- = this undo recordcontains the undo for this ITL entry

--U- = transaction committed(maybe long ago); SCN is an upper bound

---T = transaction was stillactive at block cleanout SCN

5.lck表示具体锁住了几行数据,对应有几个行锁


Scn/Fsc fsc 0x0000.02aef52d

注:这里fsc 0x0000.02aef52d是指提交的scn,这个值大于上次清除块时的csc:0x00.2aef4c9 (此scn是这个块中最小的SCN of commited)

对应col  0: [ 2]  c1 02的内容,表示第一列的值为1,同样的col  1: [ 2]  c1 02的内容也是1

/

还可以通过如下方法验证:

SELECT UTL_RAW.CAST_TO_NUMBER(REPLACE(' c1 02 ', ' ')) FROM T_600_DEMO

    UTL_RAW.CAST_TO_NUMBER(REPLACE

1 1

2 1

/

-----------------------------------------------

              《点亮梦想,拒绝平庸》

           600团队(QQ团队:851604218)

文章转载自Oracle蓝莲花,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论