在电信行业这种数据量巨大的环境中ora错是一个很常见的错误这个错误使得应用失败例如这一错误可能停止一个在深夜运行的批处理任务随后也使依赖于该任务的其他任务失败这使用户不能及时得到所需的信息(如报表没打印出来数据未被导出等等)尽管这一错误通常发生在大任务上但在小任务上也会发生 ORA通常是一个偶然出现的错误有时在发生了该错误以后重新运行该任务就有可能不再碰到类似的错误这个错误最麻烦的是它并不会立刻发生运行时间长的任务在错误失败以前可能已经运行了一段时间了(可能几个小时)只是简单地重新运行该任务并不能保证它能成功可能在运行了一段时间以后仍然失败 原因分析 ORA错的根本原因是因为oracle要保证读一致性读一致性是指当有多个用户对一个数据块内的行进行修改时这些块变髒或处于变化之中直到被确认在被确认以前它们对事务中的所有语句都是可见的但是对别的事务或语句而言是不可见的一旦确认以后对所有后继的事务或语句就都是可见的了但在事务被确认前的语句不能看到修改因为这些修改还未发生 例如事务T (如对某大表的exp操作)在 开始而事务T (如对同一大表的update操作)在 时开始因为T 需遍历一个很大的表其读取要花很长的时间而T 可能对同一个表中的数据进行基于索引的更新操作这样 T可能在几秒钟之内完成而T 可能要运行很长时间假定 分钟当T 到达T 做过修改的地方时(根据当前的S C N时间戳可以识别出新作的改变)尽管T 所进行的写已经被确认但为了保证读一致性它不会读到修改后的数据它只访问在 时的数据在 时所做的改变不能被读取 T 从回滚段中读取改变前的数据以保证读一致性但因为事务T已经提交T事务使用的回滚段oracle认为已经可以重新利用当回滚段太少或事务较密集时oracle有可能会用新事务覆盖掉原来T事务的回滚段这时T事务读到被T修改过的数据时再从回滚段中就无法找到修改前的数据这时就会报ORAsnapshot too old错 下面我们可以结合实例来将此过程回溯一遍 ()事务T在点开始执行了对某一个大表Test的exp操作(Test表数据量可能有几千万甚至更多)那么按照经验此操作可能需要执行分钟左右或更长; ()事务T在点分开始执行对Test表某行的update操作并且操作条件上有索引(将col为的行col值由修改为)故此操作很快完成比如秒钟完成操作并commit; ()此时事务T已经执行完毕而事务T还在执行中; ()当事务T需要将col为的行导出为dmp文件时Oracle为了保证读一致性即T导出的必须是点时数据库表的值故col为的行对于T任务来说值仍然为而非; ()由于T事务在点分前就已经做完(提交)并且T认为回滚段是可以重新利用的; ()如果此时由于回滚段太少或业务量较密集oracle就可能会重新利用刚才T事务所使用的回滚段这时T事务读到此处时就会造成无法找到回滚段中修改前的数据产生错误 i中对回滚段管理 在i中可以有两种解决方法来维护事务的读一致性即或者使用自Oracle 以来就一直使用的回滚段或者是使用Undo Tablespace来进行的自动重做管理但是这两种方法不能同时使用 建议在i 中使用回滚表空间而不是i 的回滚段模式来管理数据库 ()建立undotablespace 建立undotablespace的语法如下 create undotablespace tablespace_name datafile fullpath+datafilename size XXM [autoextend on|off next XX maxsize XX]; |