【DB笔试面试180】在Oracle中,Undo的作用是什么?_数据块

 

 

Q题目如下所示:

在Oracle中,Undo的作用是什么?

 

     A答案如下所示:

 

 

Undo主要有以下几个作用:

(1)事务回滚Rollback Transaction

当一个事务修改表中数据的时候,该数据修改前的值(即前镜像,Before Image)会被存放在Undo段中,当用户回滚事务(ROLLBACK)时,Oracle将会利用在数据块ITL槽中记录的Undo块地址(Undo Block Address,Uba),然后找到相应的Undo块,接着利用其中的Undo数据(即前镜像)来将修改的数据恢复到原来的值,从而实现对事务所作的改变进行回滚。

(2)事务恢复(Transaction Recovery)

实例恢复(Instance Recovery)的第一阶段称为前滚(Rolling Forward)或者缓存恢复(Cache Recovery),第二阶段称为回滚(Rolling Back)或者事务恢复。前滚和回滚是Oracle数据库实例发生意外崩溃,重新启动的时候,由SMON进行的自动恢复的过程。所谓的前滚,是应用Redo来恢复Buffer Cache的数据,将Buffer Cache恢复到Crash之前状态,所以此时Buffer Cache中既有崩溃时已经提交但还没有写入数据文件的脏块,还有事务被突然终止而导致的既没有提交又没有回滚的事务的脏块(也就是没有COMMIT,但是DBWn已经将改变的数据刷新到底层磁盘)。前滚完成之后就可以确保联机Redo日志中所有已提交的事务操作的数据写回到数据文件中。接下来,前滚之后,任何未提交的更改必须被撤消,而回滚是在数据库做完前滚操作后并打开数据库的情况下完成的,SMON会利用Undo信息将未提交的事务全部进行回滚。具体来说,SMON进程在完成前滚后,查看Undo段头(Undo段的第1个数据块)记录的事务表(每个事务在使用Undo块时,首先要在该Undo块所在的Undo段头记录一个条目,该条目里记录了该事务相关的信息,其中包括是否提交等),将其中既没有提交也没有回滚,而是在实例崩溃时被异常终止的事务全部回滚。

(3)提供一致性读(Consistent Read)

Oracle是一个多用户系统,当一个会话开始读取数据还未结束读取之前,可能会有其他会话修改了该会话将要读取的数据。如果会话读取到修改后的数据,那么就会造成数据的不一致,出现了脏读(Dirty Read)。所以,一致性读是相对于脏读而言的。在Oracle中,一致性读是通过Undo来实现的,一致性读就是为了保证数据的一致性。在一般情况下,普通查询都是一致性读。

举例来说,假设某个表T中有1W条记录,获取所有记录需要15分钟时间。当前时间为9点整,某用户A发出一条查询语句:“SELECT * FROM T;”,该语句在9点15分时执行完毕。当用户A执行该SQL语句到9点10分的时候,另外一个用户B发出了一条DELETE命令,将T表中的最后一条记录删除并提交了。那么到9点15分时,A用户将返回多少条记录?如果返回9999条记录,那么说明发生了脏读;如果仍然返回1W条记录,那么说明发生了一致性读。很明显,在9点钟那个时间点发出查询语句时,表T中确实有1W条记录,只不过由于I/O的相对较慢,所以才会花15分钟完成所有记录的检索。对于Oracle数据库来说,必须提供一致性读,并且该一致性读是在没有阻塞用户的DML操作的前提下实现的。

那么Undo数据是如何实现一致性读的呢?在Oracle数据库中的Buffer Cache中的数据块上都会有最后一次修改数据块时的SCN。如果一个事务需要修改数据块中数据,那么会先在回滚段中保存一份修改前数据和SCN的数据块,然后再更新Buffer Cache中的数据块的数据及其SCN,并标识其为“脏”数据。当其它进程读取数据块时,会先比较数据块上的SCN和自己发出SQL语句时刻的SCN,分为以下两种情况:

① 如果该数据块头部的ITL槽上记录的SCN大于自己查询时刻的SCN,那么表示该块被更新过,此时就要借助Undo块了。在该数据块头部的ITL槽上记录了对应的Undo块的地址(Uba),根据Uba就可以找到对应的Undo块。如果发现该Undo块的ITL槽的SCN号也较大,证明该Undo块也不可用,那么需要在该块的ITL槽上继续寻找上一个Undo块地址,层层递归,最终找到SCN号比发出查询的SCN号小的Undo块,将该Undo块中的被修改前的数据取出,从而构建出发出SQL语句时刻的数据块内容,这样的数据块叫做CR(Consistent Read)块。但是在查找的过程中,可能会发现当前Undo块里记录的ITL槽的SCN号比上一个Undo块里记录的SCN号还要大。这种情况说明由于事务被提交或回滚,导致当前找到的Undo块里的数据已经被其它事务覆盖了,于是就无法再找出小于等于发出查询时的那个时间点的SCN号,这时Oracle就会抛出一个非常经典的错误--ORA-1555,也就是snapshot too old(快照过旧)的错误。对于DELETE来说,其Undo信息就是INSERT,也就是说该构建出来的CR块中就插入了被删除的那条记录。

② 如果数据块头部的ITL槽(事务槽)上记录的SCN小于等于自己查询时刻的SCN,那么分为两种情况:第一,若被查询的块上没有活动的事务,则表示该块没有被更新过,是可用的,可以直接读取该数据块上的数据;第二,若被查询的块上有活动的事务,则需要找Undo的前镜像数据。

(4)实现闪回功能

闪回功能中的闪回查询(Flashback Query)、闪回版本查询(Flashback Version Query)、闪回事务查询(Flashback Transaction Query)和闪回表(Flashback TABLE)都是基于Undo表空间中的回滚信息实现的。

 

 

 

【DB笔试面试180】在Oracle中,Undo的作用是什么?_oracle_02

About Me:小麦苗

● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用

● 版权所有,欢迎分享本文,转载请保留出处

●  QQ群:230161599

● 题目解答若有不当之处,还望各位朋友批评指正,共同进步

【DB笔试面试180】在Oracle中,Undo的作用是什么?_oracle_02

 

【DB笔试面试180】在Oracle中,Undo的作用是什么?_面试_04