undo表空间的作用及ora-01555
下面我们通过DML操作,由浅入深的解读undo表空间的作用及ora-01555错误的产生:
一、当我们发出DML语句,update t set col = ‘B’ where col = ‘A’;oracle内部是怎么执行的呢:
1、 在shared pool内进行解析,生成执行计划(具体请先了解oracle内存结构易做图享池);
2、 通过执行计划找到col=’A’数据的位置,例如此数据存在10号数据文件54号数据块内;
3、 进程在buffer cache(详细请先了解oracle内存结构中buffer cache)中找到空闲的undo块,如果没有,则到undo表空间中找到一个可以使用的undo块,并调用到buffer cache中,假设次undo表空间为11号数据文件,此undo块为24号数据块;
4、 将改变前的值,也就是A放入到undo块中;
5、 由于undo数据块发生变化,所以产生重做记录,假设重做记录行号为120;
行号
事务id
File#
Block#
row
column
value
120
T1
11
24
10
col
A
6、 从buffer cache中找到54号数据文件,如果没有发现,从10号数据文件中调用;
7、 将B写入到54号数据块中,由于数据块发生了变化,所以产生重做记录,行号为121;
行号
事务id
File#
Block#
row
column
value
121
T1
10
54
10
col
B
8、 控制权返回给用户,在SQL*PLUS中会显示光标下移;
9、 当用户发出commit命令时,会触发LGWR进程,将120和121两条重做日志从logbuffer中写入到联机日志文件中,同时将54号数据块和24号undo块的头部所记录的事务状态标记设置为已经提交;
10、 此时54号数据块和24号数据块并不一定被DBWn写入到10号和11号数据文件中(存在于内存中),此时称之为脏块,只有当脏块达到一定程度才会触发DBWn将脏块写入到数据文件中;
二、undo的作用:
提供一致性度(consistentread)、回滚事务(rollback transaction)、实例恢复(Instance recovery);
1、consistent read:
什么是consistent read?
例子:T表中含有1000条数据,select * from T需要15分钟,目前为9:00,用户A发出select * from T语句,9:10时,用户B将第1000条记录delete掉,并且提交,那么9:15时A用户读取多少条记录?
如果返回999行,说明发生了脏读,但是数据库是不允许发生脏读的,所以提供了一种consistent read,及返回1000行,那么consistent read是怎样的过程呢?
首先用户A发出检索命令后呢,通过sharedpool的解析已经知道所要检索的数据位于哪些数据文件的数据块中,在读之前,用户A进程将记录下9:00时的scn号,比如此时的scn号位scn9:00,9:00之前的scn号一定是小于等于scn9:00,在检索数据块是要比较数据块头部ITL槽的scn号,如果小于等于scn9:00,说明数据块没有发生过改变,可以直接读取,如果大于scn9:00则说明数据块已经发生了改变,于是借助undo,应为undo还保留了改变前的值,此过程就叫做一致性度;
那么是怎么找到这个undo的呢?
是因为数据块的ITL槽除了记录scn号外还记录和undo的地址,我们可以根据这个地址找到undo块,从而构建出修改前数据块的内容,这样的数据块叫做CR块。
假如9:11分,用户C又插入了两条记录(并且假设表T的initrans为1,也就是一个ITL槽),那么又会怎么样呢?
oracle在记录undo的时候,不仅记录改变前的数据,还记录了改变前数据块头部的ITL信息,因此在9:10分是B用户在删除时(位于N数据块,此时N数据块头部ITL为[undo_block0/scn8:50]),提交后数据块ITL信息为undo_block1/scn9:10,undo块及undo_block1里面除了修改前数据还保存undo_block0/scn8:50,9:11分C用户在N数据块中做insert操作,那么N数据块的头部ITL信息为undo_block2/scn9:11,undo_block2除了记录更改前的信息外还记录undo_block1/scn9:10,用户在9:15的时候检索数据发现N数据块的scn号大于scn9:00,读取undo_block2,但是发现undo_block2种信息scn9:10也大于scn9:00,所以就查找undo_block1,发现undo_block1中信息scn8:50小于scn9:00可以读取,构建出修改前数据块内容,完毕;
undo表空间只要是事务结束后就可能被覆盖,假如在9:14的时候undo_block1被覆盖了,那么9:15分会怎么样呢?
ora-01555错误。snapshot too old,此时ora-01555的错误经过上面的分析,已经详细的阐明;
2、rollback transaction:
当用户发出rolback命令是,oracle会利用ITL槽中记录的undo块的信息,找到原来的值,写到数据块中。
3、Instance recovery
实例恢复发生的时刻,数据库启动以后(startup),不需要DBA干预,数据库自行解决。
实例恢复分为两种,前滚和后滚。
前滚(roll forward)也称cache recovery,利用redo日志,注意不是archive log。DBWR把rodo log files中的所有的内容读到内存中分析并全部写到数据文件中。
后滚(roll back)也称transaction recovery,利用undo,将写在数据文件中的数据但是还没有提交的或者来不及回滚的删除掉。