Oracle死事务处理的几个方法

死事务,一般是事务正在跑的时候,被kill掉了,或者数据库shutdown abort了,那么当数据库再次启动的时候,这些事务就需要做回滚。


可以通过下面的语句查到回滚的事务:


select * from v$fast_start_transactions;

或者

select * from x$ktuxe where KTUXECFL='DEAD' AND KTUXESTA!='INACTIVE'

根据上面的语句,我们可以查到事务的undo的segment id(USN或者KTUXEUSN),undo的slot(SLT或者KTUXESLT),和undo的sequence(SEQ或者KTUXESQN)。


根据USN,我们可以查到undo segment:


select * from v$rollname where usn=xxx

根据上面的语句,我们可以dump出undo block:


alter system dump undo block "" XID ;

alter system dump undo block "_SYSSMU33$" XID 33 56 7463;

然后根据dump出来的trace file,可以判断object number(objn)或者object id(objd)


cat xxx.trc |grep objn

* Rec #0x45 slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

* Rec #0x44 slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

* Rec #0x43 slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

* Rec #0x42 slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

* Rec #0x41 slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

* Rec #0x40 slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

* Rec #0x3f slt:0x1f objn:601130(0x00092c2a) objd:601130 tblspc:20(0x00000014)

...

此时,我们根据object id,可以在数据库里面找到回滚的object的对象:


select * from dba_objects where object_id='601130';

此时,如果你select count(*) from 这个表,你会发现在回滚完前,这个很简单的select操作会一直处于”db file sequential read”的等待,而且对应的p1是file file,是undo 表空间的数据文件。


我们继续,要查回滚死事务的时间,可以利用x$ktuxe,注意看其单位时间内减少了多少KTUXESIZ,即减少了多少个undo block。根据这个速度,可以估算回滚速度。注,这个速度只是大概的,有时候往往会非线性的减少。


加快回滚速度,我们需要用到一个参数fast_start_parallel_rollback,这个参数默认是low,即2倍cpu数的并发度,进行并发的回滚。我们可以设置成high,即为4倍cpu数的并发度进行回滚。


而high的时候,有时会用去比较多的资源,特别是cpu资源,会看到很多并发进程ora_pnnn,同时去查v$px_session的话,会发现他们的qcsid是smon的进程。在很高的并发度下,会影响生产的稳定,有时甚至撑爆了process数导致应用无法连接,因此需要特别的注意。我们对fast_start_parallel_rollback进行调整,可以调整成low甚至false。


而并发度如果是high或low,4倍或2倍的cpu数,也会受到另外一些参数的影响,如PARALLEL_MAX_SERVERS,这个才是真正最大的并发度设置。


PARALLEL_MAX_SERVERS这个参数的默认值为PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 5。PARALLEL_THREADS_PER_CPU 和CPU_COUNT都是初始化参数。concurrent_parallel_users 根据是否启用automatic memory management ,如果禁用automatic memory management 则这个值为1,如果pga自动管理则这个值是2,如果是automatic memory management 启用,则这个值是4。


另外,我们还可以

_cleanup_rollback_entries

,从默认值100改到400,来加快并发回滚的速度,该参数的意义是number of undo entries to apply per transaction clean。


除了上面说的加快,或者减慢(参数往小了调),我们还可以暂时禁用smon的恢复,用10513的事件:


SQL> oradebug setorapid 'SMON's Oracle PID';

SQL> oradebug event 10513 trace name context forever, level 2

恢复使用:


SQL> oradebug setorapid 'SMON's Oracle PID';

SQL> oradebug event 10513 trace name context off

那么在什么情况下我们需要加大并发,什么时候需要串行?


在一般情况下,并发的回滚总是比串行的快,我们一般在系统资源可以接受的范围内采用并发回滚,但是,有一个情况例外,就是并发的子进程之间存在资源冲突的情况。


在并发子进程之间需要的资源冲突时,往往此时smon的等待事件是长期处于

Wait for stopper event to be increased

,而子进程的等待事件是较多出现

Wait for a undo record

。此时,就是子进程冲突了。并发的回滚速度反而不如串行的回滚速度。


冲突时,我们需要把fast_start_parallel_rollback 改成 false


请使用浏览器的分享功能分享到微信等