Oracle事务槽wrap#上限问题

问题背景:

        近期遇到了一个Oracle回滚段事务ID达到上限的问题,应用前台语句操作失败,出现ORA-01558: out of transaction ID's in rollback segment _SYSSMU10_4119033733$报错。

问题分析:

        第一次遇到该报错,先到Oracle mos上查了一下ORA-01558报错的相关资料,找到了一个比较接近的案例,MOS ID:Bug 19700135 - ORA-600 [4187] when the undo segment wrap# is close to the max value of 0xffffffff (Doc ID 19700135.8),根据文章的描述,报错产生的原因是由于回滚段里面的事务槽由于事务的频繁申请,导致wrap#达到上限值0xffffffff(4294967295),致使事务申请失败,事务槽每分配给一个事务,wrap#就会递增,每次的递增值并不固定,但单次递增值不超过16。

        文档还给出了一条查询语句,用户确认当前回滚段是否出现wrap#达到了上限值的问题,通过查询undo基表x$ktue([K]ernel [T]ransaction [U]ndo transaction [E]ntry),找出wrap#在[-429496730,0]区间的回滚段

select b.segment_name, b.tablespace_name 
         ,a.ktuxeusn "Undo Segment Number"
         ,a.ktuxeslt "Slot"
         ,a.ktuxesqn "Wrap#"
   from  x$ktuxe a, dba_rollback_segs b
   where a.ktuxesqn > -429496730 and a.ktuxesqn < 0
       and a.ktuxeusn = b.segment_id;

        在报错的数据库执行该查询语句,可以看到查询出来回滚段的确为报错回滚段_SYSSMU10_4119033733$,但这里为啥使用这个范围条件[-429496730,0]进行查询,包括查出来wrap#的数量含义,哪个事务槽有问题,文章并没有进行详细说明,为此,我对回滚段的wrap#上限值进行了研究测试。

回滚段事务槽warp#上限研究测试:

        我们以UNDOTBS1表空间里面的一个回滚段_SYSSMU3_2471395754作为研究测试对象,dump出了回滚段的头块。

---使用dump undo header
alter system dump undo header '_SYSSMU3_2471395754$';
---也可以通过dba_segments查出回滚段的头块ID,再通过dump datafile方式
alter system dump datafile 3 block 128;

       分析dump的回滚段头信息,单个回滚段里面34个事务槽,从0开始,每一个事务槽都有各自对应的wrap#大小,这里我们将研究测试的对象缩小到0号槽0x00,当前的wrap#为0x0fae,转成10进制为4014。

        再通过x$ktue查询该回滚段的wrap信息,可以看到列ktuxeslt和ktuxesqn分别对应事务槽slot和wrap#,查到到数值为0和4014,与dump回滚段头信息一致。

select b.segment_name, b.tablespace_name 
             ,a.ktuxeusn "Undo Segment Number"
             ,a.ktuxeslt "Slot"
             ,a.ktuxesqn "Wrap#"
       from  x$ktuxe a, dba_rollback_segs b
       where a.ktuxeusn = b.segment_id and b.segment_name='_SYSSMU3_2471395754$';

        使用bbed打开回滚段所在的块,通过find命令查询事务槽的offset,需要注意的是对于Linux,由于字节序是little-endian,所以要低位开始读取,比如dump文件里面的wrap#为00000fae,在bbed显示的顺序为ae0f0000,所以查找wrap#的位置通过find /x ae0f,查到0号槽的wrap#的offset为6200-6203。

        通过bbed修改0号槽的wrap#的offset为上限值ffffffff,模拟wrap#达到上限值。

        再次查看x$ktue里面回滚段0号槽的wrap#大小,可以看到wrap#显示的值为-1。

       通过set transaction user rollback segment方式测试事务指定使用wrap#为-1槽所在的回滚段,看看会出现什么样的问题。

begin
for i in 1..100000 loop
 set transaction USE ROLLBACK SEGMENT "_SYSSMU3_2471395754$";
 delete from test.test where rownum<2;
 commit;
end loop;
end;
/

        可以看到操作会话直接异常断开ORA-03113,并且后台日志出现大量的ORA-00600: internal error code, arguments: [4194], [], [], [], [], [], [], [], [], [], [], []报错,语句无法正常执行。

        通过bbed重新修改wrap#为fffffffa(4294967290)离上限值只差距5。

        再次查看x$ktue里面回滚段0号槽的wrap#大小,可以看到wrap#显示的值为-6。

        再次通过set transaction user rollback segment测试事务指定使用wrap#为-6的回滚段,可以看到这一次复现了ORA-01558: out of transaction ID's in rollback segment _SYSSMU3_2471395754$的报错。

       再次查看x$ktue里面回滚段0号槽的wrap#大小值为-2,没有再变化,接近最大值ffffffff。

        修改wrap#为最大值的一半:7fffffff,可以看到x$ktue里面显示的值为2147483647。

        修改wrap#为最大值的一半加1:80000000,可以看到x$ktue里面显示的值为-2147483647。所以,x$ktue里面显示的wrap#的值范围将ffffffff且为了两段,第一段[0,2147483647],第二段[-2147483647,-1]。wrap#越接近-1的代表该事务槽slot接近上限。

        这时候我们再看回mos文档给的查询语句,a.ktuxesqn > -429496730 and a.ktuxesqn < 0查询条件的含义就是查询wrap#的值范围接近ffffffff上限的事务槽

        而之前问题查到的结果回滚段_SYSSMU10_4119033733$事务槽里面slot 14的wrap#为-17,接近上限值-1,就是导致出现ORA-01558: out of transaction ID's in rollback segment _SYSSMU10_4119033733$报错的原因。

问题修复:

        对于回滚段事务槽达到上限的,可以通过重建undo表空间的方法进行修复。

        注:重启数据库,不会导致回滚段wrap#清空。

        重建undo表空间的操作步骤。

--创建新的undo表空间
SQL> create undo tablespace <New Undo Tablespace name> datafile size <new size>;
--设置当前的默认表空间为新undo表空间
SQL> alter system set undo_tablespace=<New Undo Tablespace name>;
--查看旧undo表空间是否存在online的回滚段,即使切换了默认的undo表空间,已经被事务分配使用的旧undo回滚段依然在使用,直到事务提交之后才释放
SQL> select status,segment_name from dba_rollback_segs where status not in ('OFFLINE') and tablespace_name=<undo tablespace to be dropped>;
--需要等待旧undo表空间没有online的回滚段才能drop 旧的undo表空间
SQL>Drop tablespace <tablespace_name> including contents and datafiles;
​

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值