sql执行过程——延迟块清除

delete
1.Oracle读Block到Buffer Cache(如果该Block在Buffer中不存在)
2.在相应回滚段段头的事务表中创建一个undo条目(undo条目指向的一块空间)
3.将要变化的记录(不是整个数据块)的前映象放到undo中。如果这时有别的会话需要读取这条记录,oracle先将这条记录所在的数据块复制一份,然后用undo中那条记录的前映像"旧化"这个数据块,这样一致读的数据块就构建完成了。
4.在redo log buffer中记录此次操作的产生redo 数据和undo数据
5. 在Buffer Cache中的相应数据块上修改记录,并且标记相应的数据块为Dirty

提交(COMMIT)
1.Oracle产生一个SCN
2.在回滚段事务表中标记该事务状态为commited
3.LGWR Flush Log Buffer到日志文件
3.如果此时数据块仍然在Buffer Cache中,那么SCN将被记录到Block Header上,这被称为快速提交(fast commit)
4. 如果内存不够,dirty block已经被写回到磁盘,那么下一个访问这个block的进程,会定位到数据块上要获取的行,从行头找到数据块头中itl事务表中
对应的事务条目,从该事务条目中判断该事务有没有提交(因为在提交前就写入磁盘了,来不及标记提交标记),如果没有提交,将会根据从该事务条目中找到在回滚段中对应的地址,根据地址进入
回滚段中获取该事务的状态。如果事务被提交,则将提交SCN并写回到Block Header中的itl事务表中的对应的事务条目中。这被称为延迟块清除。
如果回滚段中的事务条目由于时间太久已经被覆盖了,那oracle会从当前回滚段中找到一个最小的commit  scn更新这个延迟块清除的块的块头中的itl,
从而完成块清除。(这虽然不准确,但是是安全的,对于数据访问也不构成影响。所以叫 upper bound ,猜测的一个scn的上限。)
如果当前的查询时的scn比这个最小的commit   scn还小,说明事务的提交scn可能也大于当前查询的scn。则产生01555错误,由于报错后写回了一个当前回滚段中最小的提交scn,那么下次就不会再触发
01555这个错误了;如果当前的查询时的scn比回滚段中最小的commit scn大,那么当前查询的scn肯定大于已经被覆盖的事务的scn,则可以直接用这个延迟清除的块构建一致读

数据块写回磁盘——回滚段中记录还在——事务未提交:重新读入数据块,构建一致读,正常读取
数据块写回磁盘——回滚段中记录还在——事务已提交:重新读入数据块,构建一致读,正常读取
数据块写回磁盘——回滚段中记录被覆盖:延迟块清除(如上所诉)
数据块在内存——回滚段中记录还在:正常读取
数据块在内存——回滚段中记录被覆盖:ora-01555错误,回滚段太小

一致读时,oracle会一直找到(或者构建出)比当前查询scn还小的且已经提交的数据版本。如果找不到,就是ora-01555错误。
那假如事务槽被覆盖了怎么实现一致读呢?
如果事务槽被覆盖了也没事,因为当前事务槽中 的UBA 可以找到回滚段地址 回滚段中除了记录数据的 before image 外 还记录了被它覆盖的事务槽的记录。可以形成一个链表
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值