图解:
一个undo段,里面有一个事务T1,修改了一个数据块,然后T1提交了,还有一个事务T2,T2也要修改同样的数据块,因为事务槽所对应的事务T1已经提交,事务T2就可以覆盖事务T1在数据块中所对应的事务槽,要覆盖事务槽就要修改事务槽中的数据,就会产生undo,对于数据块来讲,修改任何数据都会产生undo;因为T2要覆盖事务槽就要修改数据,就要把事务槽里面的数据拿出来放到undo段的一个块里,然后新的事务槽的xid指向事务T2了,这时候T2也提交了;
我们就来找,找这个数据块数据修改的历史,对于这个数据块来说,被事务T1修改过,也被事务T2修改过,如今我们能看到事务T2修改后的数据,这时候,我们也可以看到事务T1修改过的数据,从T2往前推就可以找到T1修改前的数据;有T3,T4.....也是云云
假设数据库建立以后undo表空间足够大,没有边界的大;对于数据块来讲,数据库可以找到全部的数据块的修改信息,就是一个数据块被多个事务修改了
如果如今将undo returntion设置为:24小时,然后将表空间设置为:gurantee属性;也就是这个表空间不绝存储24个小时的数据,那么可以访问24小时之内表的每个时候的数据;
select * from t; 访问如今的数据;
select * from t as time of 13:30:01;访问13:30:01时修改过的全部数据块的数据
ORA-01555错误
图解:
比如,如今oracle有一个t表,t表比较大,下面有很多很多块;在8:50访问t表,在8:55的时候有一个事务修改了一个数据块,数据块里面的SCN被修改为8:55,然后提交了;
假设9:00的时候读到末了一个数据块的末了一行,但是8:55删除了一行数据;假设t表有一万行,8:00的时候开始读,到9:00的时候会读到多少行数据?
读取了一万行;
因为对于select来讲,读到末了一行数据时,这行数据对应的事务已经提交了,按道理,这一行上没有未提交事务,删除数据已经提交了,不能被读,但是还是读到了10000行数据。oracle在读select开始的时候,记住当时时间点全部数据块的SCN号:850,oracle做了一个假设,并且假设成立:就是将要访问的表在8:50这个时候,所对应的全部数据块的事务槽,它们的SCN号都应该小于等于900,突然让时间停止,将全部数据块读一遍。当读到末了一个块的时候,发现SCN号是:855,然后找末了一条数据之前的数据,通过undo构建CR块,找出该行数据SCN号为:850时的数据;
在8:57的时候,8:55的undo块被覆盖了。导致8:50的select读数据的时候,去undo块中找,发现数据没了,无法构建CR块,oracle就会报出ora-01555错误,报出ora-01555错误的因为:snapshot too old(快照太旧)或者select读取的时间过长
导致ora-01555错误的缘故原由:
可能是snapshot too old(快照太旧)或者select的执行时间太长,还有就是undo空间压力很大,undo数据被快速覆盖;该错误,会指定哪个SQL引起的问题
select访问的是生产表,触发ora-01555这个错误,缘故原由可能是undo空间太小;
select访问的是字典表,oracle做ddl的时候,向系统表空间的数据字典做insert操作,会将修改信息写到系统表空间的undo段中专门给字典表做回滚;
所以访问的是字典表的时候,发生01555错误是系统表空间的undo段引起的,很可能是一个bug,mos中查找。
回滚