以上脚本是在Oracle9.2上测试,Oracle对UNDO的处理非常复杂,这里介绍只是常用的一些DML产生UNDO估算方法,从估算公式可以看出,
一、Oracle DML SQL回滚逻辑简介
数据库事务由1个或多个DML(insert,update,delete) SQL组成,我们知道Oracle数据库在进行DML操作需要使用UNDO表空间来保存事务回滚的信息,对于每种DML操作回滚的UNDO信息都不一样,大致如下:insert操作很简单,只要保存记录插入到数据块及数据块内的槽号,回滚时只要根据数据块号及槽号做删除就可以了。
update操作需要保存记录位置,还需要保存变更的字段原内容,回滚时采用原值即可。
delete操作麻烦一些,不仅要保存记录位置,还需要将原有记录的内容全部保存下来,回滚时才能组成新的数据插入进去。
如果表上有索引,则DML操作同时需要在UNDO表空间中保存索引相关的回滚信息。
DML操作主要有以下几方面的开销构成:
获取锁(CPU开销)
定位要变更的记录(离散IO开销)
记录回滚信息(CPU+IO开销)
变更记录(CPU开销)
记录重做日志(顺序IO开销)
数据块写入(异步离散IO开销)
因为DML操作过程中记录回滚信息占用了非常大的一块资源,为了更好的估算DML操作需要回滚空间的大小,本文介绍了一些常用操作的估算方法及验证示例。
二、如何查看事务UNDO使用空间
如何查看事务操作使用的UNDO空间,Oracle提供了系统视图V$TRANSACTION,里面保存了当前数据库活动事务的主要信息,我们可以用如下SQL来查看:
由于测试环境就我一个人使用,不存在并发,为简化操作,,忽略会活参数,简化的SQL如下:select USED_UREC from v$transaction;
通过START_UBAFIL及START_UBABLK我们可以dump回滚数据块的分析,如下所示:
alter system dump datafile START_UBAFIL block START_UBABLK;
dump好后再通过日志文件分析数据块内的详细信息,笔者也是通过这样的方法来确认计算公式,因为dump出来的内容比较复杂,是Oracle的具体实现细节,所以本文不介绍dump内容,有兴趣的同学可以自己测试。
三、测试准备