Skip to content

记一次Oracle并行回滚带来的负面影响

并行回滚是oracle的一个特性,初衷是为了加速失败事务的回滚,缩小回滚时间,Oracle设计这个特性的初衷大多时候都是实现了,但是在一些情况下,这个初衷变成了硬伤,就像七伤拳一样,伤害是不错,但是自己也要受几份内伤。最近碰到2次因为这个特性导致的数据库hang或者部分业务hang的情况。

我根据经验总结一翻并行回滚的情况怕遇见2种情况:

1.并行回滚相关的bug,此类bug有不少
2.大事务的回滚

相关bug:
pxre bugs

关于事务恢复的东西可以参考文章:ID 1494886.1。这里介绍前天碰到的并行回滚导致阻塞的问题,情况是对某张表进行exp导出,结果很慢很慢,等了一晚上都没导完成,采用create table as select的方式也hang住了,信息传到到我这里时候我的反应是事务阻塞,初始判断应该是在段头或者回滚上的阻塞,远程过去时候,并不急着看系统的总体情况,和客户先沟通一翻情况发生的时候是下午1点多开始的,exp和ctas操作也是1点之后,稍微梳理相关的语句信息后初步决定做这几步操作:

1.分析alert.log
2.分析block=1的进程是否存在,是否存在死事务
3.分析发生情况时候的awr以及ash
4.分析发生情况时候的io/cpu情况
5.分析exp/ctas操作时候exp进程的等待

原本打算根据如上的情况后再做下一步的操作,结果在第3个步骤时候就已经发现了问题。alert日志没有报错已经相关有作用的信息,系统中也没有存在的阻塞进程,而AWR中top 5 event确实和我预测的方向在一条线上,具体看如下:

Top 5 Timed Foreground Events

Event Waits Time(s) Avg wait (ms) % DB time Wait Class
wait for a undo record 484,175 51,190 106 79.33 Other
db file sequential read 980,647 7,411 8 11.49 User I/O
db file scattered read 29,860 723 24 1.12 User I/O
DB CPU   354   0.55  
read by other session 50,013 269 5 0.42 User I/O

以上的信息提示的非常明显,在1小时内存在大量wait for a undo record等待,而此期间内已经关闭了业务,只有exp和ctas操作,可以进一步的判断阻塞的问题应该和涉及对象存在回滚事务有关,当然现场通过undo的信息确认了回滚的对象确实和exp的对象为同一个,具体的方法可以参考文章 《通过undo record找到对应回滚对象信息》 http://www.ludatou.com/?p=2258。

为了确定是并行回滚导致的问题期间收集了以下信息进行判断:

1.FAST_START_PARALLEL_ROLLBACK参数值为low

2.系统中存在死事务

dead tran
3.系统中存在一个回滚事务预估回滚到8月10号

tx recoerinfo

通过awr和收集的信息确定了问题的根源应该就是并行回滚。当然多个并行的回滚进程并没有去判断,在windows平台在系统级别我跳过了这步,为了尽快恢复业务,随即确认了验证性的解决方案,对fast_start_parallel_rollback进行在线变更为false,在对此参数设置不同值的时候,smon进程会停止对该事务的恢复并根据新的参数值重新恢复该事务,该参数是动态的,因此改为false后可以遇见的是该事务会串行顺序回滚,并且速度应该不错,结果并没有让我失望,看下图便知:
tx recover after

当然,现场可以通过smon禁止回滚的方式让exp过去,毕竟是生产,有更好的办法,为啥要用oradebug呢?期间的问题还有不少值得思考,比如undo record的争用,并行回滚进程的资源耗用等,这里不做描述了。

建议关注11g数据库password_life_time

Oracle 11g 之前默认的用户时是没有密码过期的限制的,在Oracle 11g 中default的profile启用了密码过期时间是180天,也就是password_life_time值为180,虽然是个小细节,但是很多客户在迁移到11g后有规律性的都在半年后出现了密码错误无法登陆的问题.

如下:

select * from dba_profiles where profile='DEFAULT' and resource_name='PASSWORD_LIFE_TIME';

PROFILE       RESOURCE_NAME       RESOURCE LIMIT
------------ -------------------- -------- -------
DEFAULT       PASSWORD_LIFE_TIME  PASSWORD 180

当过期时候系统会报错ORA-28002.当遭遇这个问题时候可以通过以下方式解决:

    1.新建profile,对用户指定新的profile.
    2.通过对用户重设密码(密码可以和原来一样).

    命令为:

    alter user username identified by password.
    

    3.针对默认的profile的password_life_time设置为unlimited

    命令为:

    alter profile default limit PASSWORD_LIFE_TIM 180.

以下是profile里的关于password的设置类目解释:

    FAILED_LOGIN_ATTEMPTS
    设定登录到Oracle 数据库时可以失败的次数。一旦某用户尝试登录数据库的达到该值时,该用户的帐户就被锁定,只能由DBA能解锁。
    PASSWORD_LIFE_TIME
    设定口令的有效时间(天数),一旦超过这一时间,必须重新设口令。缺省为180天(11g,10gUNLIMITED).
    PASSWORD_REUSE_TIME
    许多系统不许用户重新启用过去用过的口令。该资源项设定了一个失效口令要经过多少天,用户才可以重新使用该口令。缺省为UNLIMITED.
    PASSWORD_REUSE_MAX
    重新启用一个先前用过的口令前必须对该口令进行重新设置的次数(重复用的次数)。
    PASSWORD_LOCK_TIME
    设定帐户被锁定的天数(当登录失败达到FAILED_LOGIN_ATTEMPTS时)。
    PASSWORD_GRACE_TIME
    设定在口令失效前,给予的重新设该口令的宽限天。当口令失效之后回,在登录时会出现警告信息显示该天数。如果没有在宽限天内修改口令,口令将失效。
    PASSWORD_VERITY_FUNCTION
    该资源项允许调用一个PL/SQL 来验证口令。Oracle公司已提供该应用 的脚本,但是只要愿意的话,用户可以制定自己的验证脚本。该参数的设定就是PL/SQL函数的名称。缺省为NULL.

通过undo record找到对应回滚对象信息

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

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 "<undo segment name>" XID <USN> <SLT> <SEQ>;

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:223312(0x00092c2a) objd:223312 tblspc:20(0x00000014)

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

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

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

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

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

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

...

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

select * from dba_objects where object_id='223312';

关于11g数据库基础审计的初始注意事项

目前11g已经有些年份了,大部分的系统已经迁移或者升级到11g的版本,而后续上线的大部分系统都是以11g为主.在11g以上的版本中数据库的基础审计和以往版本不同,11g以后的版本默认是开启的.基础审计这个功能大部分时候并不是很受关注,一来是比较简单就能设置完成,二来国内对信息数据安全的不够注重的环境也让很多dba在数据库安全层面未有太多落实.所以在基础设计这块在数据库构建之处也容易忽视.

审计在默认开启的情况下,主要影响是2方面:

    1.审计记录在长久记录后,会占用较多的空间,而审计记录表默认是存放在system表空间.
    2.在审计记录膨胀后,容易对一些类型的应用产生性能上的影响.

在初始构建11g实例时候,对审计处理并不是一味的关闭处理,主要是考虑开启的必要性需求,以及如果开启后如何去管理审计记录.以前我遇见过这样的需求,主要是针对审计开启后的审计记录管理问题.关闭倒是容易,一条命令就可以结束.反倒是开启后对审计记录的管理.可以参考以下2个文章对审计记录表存放位置挪移到别的表空间,同时制定定期的删除策略.

从ASM直接读取数据的研究思考

从ASM直接读取数据分为2种情况考虑

1.直接读取datafile文件
2.直接读取datafile中的objects

直接读取datafile文件的原理,目前MDATA和AMDU均实现了此功能

先从第一种从ASM中直接读取datafile的情况,这种case也是比较简单的。Datafile在文件系统中的单位是8k块为单位,在从数据字典中读取对象时候从对应的块地址可以直接读文件获取,因此文件系统中用mdata,dul等工具恢复对象的实现方式上虽然复杂,但是相比asm要简单不少,ASM也是一种文件系统,只是是封装的文件系统,普通的操作系统不能直接访问asm中的对象,必须通过asm,asm中构成asm文件的单位是au,因此datafile也是由多个au组成,而au是根据asm的条带大小和条带深度分部的,datafile只能存放于ASM 的DG中,不能跨DG,每个DG由1个或者多个disk组成,在DG中组成datafile的au是根据条带算法分部在dg里面的多个盘里的,因此需要从asm中恢复出datafile,需要知道au的分部情况,每个datafile包含au的地址范围。而ASM中dg的file directory(文件分配表)则可以读到此信息,因此只要找到对应文件的file dir就能找到对应asm file的au分布信息。有兴趣可以研究下asm的1号文件,每个文件在1号文件中都有4k的au 分布信息,1号文件至少为2个AU,海波写过一篇文章专门介绍过用c语言实现从asm中读取datafile,当然我看到的版本只处理30M au分布信息的file diretory(第一个AU),如果文件number超过256则需要在下一个au中读取相关文件的au分布信息。到这里恢复datafile已经不是什么大问题。

直接读取datafile中的objects的原理思路

这个会比较麻烦,用一句话提示吧,数据字典固定同时构建一份au分布信息表类似X$KFFXP。