love wife & love life —Roger的Oracle&MySQL技术博客

Phone:18180207355 提供专业Oracle&MySQL数据恢复、性能优化、迁移升级、紧急救援等服务

ORA-30025: DROP segment ‘_SYSSMU559$’ (in undo tablespace) not allowed

这里是今天一些学生的问题,下午没事研究了一下。 发现非常的奇怪,大家一起来探讨下。 对于没有活动事务的情况,其回滚段的状态居然是Pending offline.

根据描述,这个undo表空间已经切换了1周了,而且数据库中最长的会话登陆时间也就几个小时而已。怀疑是回滚段存在活动事务.

dump 该回滚段头发现比较怪异:

 

我们知道,index表示slot,而state表示事物状态,9表示inactive,10表示active。从dump 来看,根本就没有活动的事务。
但是Oracle为什么会认为这个回滚段是pending offline的呢? 他这里的信息,其实一个地方比较怪异:ktuxc里面的uba地址,应该是跟最新的一个事务对应的undo dba地址是一致的,而这里的最新的事务,index=04这个,dba地址居然是0x000000000.
针对这个问题,我进行了一个测试,花了不少时间。

Session 1:

Session 2:

切换undo之后,我们看到第6号回滚段果然变成了期望的Pending offline.下面我们来dump下该回滚段头:

我们可以看到,index=08这个事务的状态是10,表明是active. 这跟文档描述是一致的。然而学生这里的问题是没有active的事务。
为了模拟的更逼真一点,我手工把这个事务给提交了,通过bbed来完成.

+++ 首先把测试表里面这个数据块中的事务给提交了

ok,数据块修改完毕了,下面来修改回滚段头。

首先定位该回滚段的段头块地址:

定位到回滚段头地址之后,我们就可以利用bbed来进行修改了。 注意,bbed是无法直接map非system 回滚段头块的,因此修改

起来相对比较费劲,但是其结构和system 回滚段头的结构并没有太大的差异。
+++ 根据ffff进行搜索,定位事务,修改uel等一系列动作

通过一系列修改之后,我们发现bbed校验不在报错了。这里我们主要修改了如下几个地方:
ctl: 0x0007 –> ctl: 0x0008

index:07的事务,修改为如下: 状态从10改成9,uel从ffff改成08,同时该事务对于的scn稍微修改大一点点,我这里加3.
uel是指向下一个slot的信息,因此这里还需要把index:08的对应的uel改成ffff. 表明该事务是当前最新的一个. 修改完知道的情况:

修改完之后的情况和实际的情况就有点符合了,测试了一把,发现仍然无法直接drop。

可以看到这个试图的数据本质是来自这个x表。通过kturdflg来判断回滚段的状态。 不过这里仍然无法知道Oracle是如何来进行实际判断的。通过10046 发现本质上也读取的回滚段头:

 

从10046 跟踪来看,Oracle这里一共读取了3个块:file 1 ,block 9file 7 block 25,file 2 block 5689
file 1 block 9,不用想,肯定是system回滚段.
这里的file 7 block 25是当前的undo表空间的一个回滚段头的地址:

而file 2 block 5689 就是我们之前有问题的这个回滚段头地址。
最后想了很久,也没有明白,oracle这里的回滚段状态pending offline是如何判断出来的。
最后处理这个问题,其实方法很多,几年前写过一篇文章,用隐含参数,bbed等方式都可以很容易处理。
在10gR2版本中,最简单的方式就是这样:

随便玩玩,不要再生产随便弄,概不负责哈!大家一起来探讨下这个问题!

Leave a Reply

You must be logged in to post a comment.