undo的段头存在着一个SEQ值,当回滚段使用从A区到B区的时候,相对应的SEQ值便会加1,例如A区的SEQ值是6,则undo段使用到B区的时候变会成为7。
但是undo空间是循环使用的,当该undo段中的事务提交过了之后,相对应的块就可以被覆盖掉。如下:
当3号区使用完全之后,oracle将会重新使用1号区,并将其SEQ值加一,改为7,以此类推,新1号区使用完了之后,2号区也会被覆盖,SEQ值改为8.
但是undo空间是循环使用的,当该undo段中的事务提交过了之后,相对应的块就可以被覆盖掉。如下:
当3号区使用完全之后,oracle将会重新使用1号区,并将其SEQ值加一,改为7,以此类推,新1号区使用完了之后,2号区也会被覆盖,SEQ值改为8.
undo块覆盖的原则是即将被覆盖的undo块必须小于前一个已经覆盖过的SEQ值。如果如下图,
2号区一直有一个事务占住未被释放,等到undo再次重用到1号区的时候,1号区的值变为10。这个时候由于2号区的事务一直未被释放,oracle无法对2号区进行覆盖,也不能跳过2号区去重用3号区的undo块。这个时候oracle便会进行一次extend,在一号区和二号区中间新增一个undo区,我们称为新2号区。然后oracle便会在新2号区进行覆盖,在新2号区覆盖完成之后,如果老2号区还未提交事务,oracle便会再次申请extend,直到事务提交。这样会造成undo段短时间内消耗大量空间。如下:
如果该2号区在undo段的开头部分,这样会导致undo段大部分空间不能重用,所以oracle增加了一种steal机制。
首先确定的是undo偷窃机制的基本单位是区。例如发生上述情况:
原二号区:即三号区一直有事务在占用部分块,导致其无法被覆盖。那oracle的undo偷窃机制会启到作用,其他undo段将会把4号区偷走,此undo段便会剩下三个区,然后在新2号区后进行extend。
但是如果三号区的事务一直不提交,oracle会一直extend,导致3号区之前的区一直无法被重用,undo段一直在增加,可能会报错undo空间无法扩展。所以事务无论大小,还是要尽快提交。