转Rollback后undo到底做了些什么?
转自:http://biancheng.dnbcw.info/oracle/309191.html
Rollback后undo到底做了些什么?
从概念上讲,undo正好与redo相对。当你对数据执行修改时,数据库会生成undo信息,这样万一你执行的事务或语句由于某种原因失败了,或者如果你用一条rollback语句请求回滚,就可以利用这些undo信息将数据还原到修改前的样子。Redo用于在失败时还原事务(即恢复事务),undo则用于取消一条语句或者一组语句的作用。与redo不同,undo在数据库内部存储在一组特殊的段中,这称为undo段(undo segment)。
通常对undo有一个误解,认为undo用于将数据库物理地恢复到执行语句或者事务之前的样子,但实际上并非如此。数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但数据结构以及数据库块本身在回滚后可能大不相同。原因在于:在所有的多用户系统中,可能会有数十、数百甚至数千个并发事务。数据库的主要功能之一就是协调对数据的并发访问。也许我们的事务在修改一些块,而一般来讲往往会有许多其他的事务也在修改这些块。因此,不能简单地将一个块放回到我们事务开始前的状态,这样会撤销其他人(其他事务)的工作!
例如,我们的事务执行一个insert语句,这条语句导致分配一个新区段(也就是说,导致表的空间增大)。通过执行这个insert,我们将得到一个新的块,格式化这个块以便使用,并在其中放上一些数据。此时,可能出现某个事务,他也向这个块中插入数据。如果要回滚我们的事务,显然不能取消对这个块的格式化和空间分配。因此,oracle回滚时,它实际上会做与先前逻辑上相反的工作。对于每个insert,oracle会完成一个delete。对于每个delete,oracle会执行一个insert。对于每个update,oracle则会执行一个“反update”,或者执行另一个update将修改的行放回去。当然这种undo生成对于直接路径操作(direct path operation)不适用,直接路径操作能够绕过表上的undo生成。
为了更好的说明问题,下面做一个小小的测试,以便验证上述的正确性。以下就是一个简单测试的步骤:
(1) 创建一个新的空表。
(2) 对它做一个全表扫描,观察对该表所执行的I/O数量。
(3) 向表中填入许多行(暂时不提交commit)
(4) 回滚这个工作。
(5) 再次进行全表扫描,观察对该表所执行的I/O数量。
好了,下面我们一起来做一个简单的测试工作:
首先,创建一个空表:
hongsy@test>create table t
2 as
3 select *
4 from all_objects
5 where 1=0;
表已创建。
hongsy@test>select * from t;
未选定行
hongsy@test>set autotrace traceonly statistics
hongsy@test>select * from t;
未选定行
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
915 bytes sent via SQL*Net to client
372 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
hongsy@test>set autotrace off
hongsy@test>insert into t select * from all_objects;
已创建31620行。
hongsy@test>rollback;
回退已完成。
hongsy@test>select * from t;
未选定行
hongsy@test>set autotrace traceonly statistics
hongsy@test>select * from t;
未选定行
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
436 consistent gets
0 physical reads
0 redo size
915 bytes sent via SQL*Net to client
372 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
前面的insert 导致将一些块增加到表的高水位线(high-water mark,HWM)之下,这些块没有因为rollback而消失,它们还在那里并且已经格式化,只不过现在为空。全表扫描必须读取这些块,看看其中是否包含行。通过比较上面对同一表查询的两个统计信息我们得出:undo操作只是回滚了数据库的逻辑结构,而没有撤销其物理结构。
以上是本人近期对undo的研究之一,写下自己的学习心得,供大家讨论。限于本人学识水平,难免存在问题,请批评指正。如有异议请email:hongsy@e-u.cn。
转Rollback后undo到底做了些什么?的更多相关文章
- linux内核中宏likely和unlikely到底做了些什么?
1. 先看看它们长啥样吧!(它们有两种定义,第一种是使能了程序trace功能的宏定义,第二种是普通的宏定义,咱们分析普通宏定义吧) # define likely(x) __builtin_expec ...
- js中的new()到底做了些什么??
要创建 Person 的新实例,必须使用 new 操作符.以这种方式调用构造函数实际上会经历以下 4个步骤:(1) 创建一个新对象:(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新 ...
- Java环境的搭建及用记事本来揭露下JDK到底做了些什么
和我一样的新手想学Java就从自己搭建环境开始,请看完这边文章,我搜集资料的整合. Java的标准版本是Java SE,所说的JDK(Java Development Kits)就是Java SE的开 ...
- iOS 中push和pop到底系统做了些什么事
iOS中的push和pop是一个很常用的视图切换方法,他们是成对出现的, 简而言之,push就是压栈,pop就是出栈! [self.navigationController pushViewContr ...
- AFNetworking到底做了什么
写在开头: 作为一个iOS开发,也许你不知道NSUrlRequest.不知道NSUrlConnection.也不知道NSURLSession...(说不下去了...怎么会什么都不知道...)但是你一定 ...
- AFNetworking到底做了什么?(二)
接着上一篇的内容往下讲,如果没看过上一篇内容可以点这: AFNetworking到底做了什么? 之前我们讲到NSUrlSession代理这一块: 代理8: /* task完成之后的回调,成功和失败 ...
- dreamvc框架(三),dispartcher做了些什么
这一篇我会介绍一些dreamvc的核心类Dispatcher都做了些什么,首先我们先来看一看init方法,这是在DispatcherServlet和DispatcherFilter里面都会调用到的一个 ...
- 转 OGG add trandata 到底做了什么
有的时候我们做OGG的时候add trandata会出现异常. 这里就剖析一下add trandata到底做了什么 GGSCI (yjfora81 as ggs_admin@testdb) 2> ...
- vue.js中,input和textarea上的v-model指令到底做了什么?
v-model是 vue.js 中用于在表单表单元素上创建双向数据绑定,它的本质只是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能: 对,它本质上只是一个语法糖,但到底是一 ...
随机推荐
- express 4.x 文件上传
1.安装文件上传模块: npm install multiparty --save 2.在routes/index.js 中添加: // 引用模块 let multiparty = require(& ...
- 仅以一个前端开发人员的角度看微信小程序
看了几天的小程序(当然也包括了上手书写),才有了这篇博文,非技术贴,只是发表下个人观点,仅以个人技术能力来看小程序. 首先说下优点: 调试工具:官方的工具还是做了很多工作,包括监听文件变动自动刷新,编 ...
- unity3d使用litjson中文显示的问题
我们在使用litjson时它的编码方式是unicode的,所以我将json转成string输出时显示的是unicode的编码.这样我们显示或者保存中文时不是很方便.我们可以将中文的unicode转成能 ...
- CentOS 6.5 部署Unison双向同步服务
环境介绍: 服务器 IP Server1 192.168.30.131 Server2 192.168.30.132 1.添加主机互信: a.添加host文件(在Server1.Serve ...
- Android 不能返回 parent Activity 的问题
使用 ActionBar,开启返回按钮: 在 Activity 的 onCreate 中添加下面代码 getSupportActionBar().setDisplayHomeAsUpEnabled(t ...
- HDU 5886 Tower Defence
树的直径. 比赛的时候想着先树$dp$处理子树上的最长链和次长链,然后再从上到下进行一次$dfs$统计答案,和$CCPC$网络赛那个树$dp$一样,肯定是可以写的,但会很烦.......后来写崩了. ...
- 【Python】考虑用生成器改写直接返回列表的函数
使用生成器的好处是显而易见的,可以使代码更加清晰,同时减小内存的消耗,当函数需要返回列表,把函数改写为生成器是相对容易的. 下面这两个函数返回字符串中每个单词的索引: def index_words1 ...
- 关于mac地址的一点感想
因为怕mac地址冲突导致环路影响,所以修改了本地设备的mac地址.地址修改为 77:77:77:00:22:11, 结果导致 wlan0 下发不下来. 查看配置选项/etc/config/wirele ...
- 手动添加PopMenu出现的问题
最近在github上找了个比较酷的弹出菜单PopMenu用来做分享页面,demo下载运行OK,于是拖进项目中,一编译就呵呵了.... 一看demo目录,原来这还还引用了其他库,于是把pod下面的pop ...
- linux awk命令详解2
awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息 awk处理过程: 依次对每一行进行处理,然后输出 awk命令形式: awk [-F ...