文章目录
参考:https://www.cnblogs.com/yhq1314/p/10180158.html
redo
(重做信息)是oracle在线(或归档)重做日志文件中记录的信息,可以利用redo重放事务信息(前滚)undo
(撤销信息)是oracle在undo段中记录的信息,用于撤销或回滚事务(回滚)
undo(用于回滚数据)
你对数据执行修改时,数据库会生成undo信息,以便回滚到更改前的状态。
(这样万一你执行的事务或语句由于某种原因失败了,或者如果你用一条ROLLBACK语句请求回滚,就可以利用这些undo信息将数据放回到修改前的样子。)
从概念上讲,undo正好与redo相对。
redo用于在失败时重放事务(即恢复事务),undo则用于取消一条语句或一组语句的作用。
关注点:
-
UNDO在数据库内部存储在一组特殊的段中,这称为UNDO段(UNDO segment),或者“回滚段”(rollback segment)。
(新版oracle还提供了undo表空间用于存储先前存在undo段中的数据)
需要注意,UNDO并不能将数据库物理地恢复到执行语句或事务之前,只是逻辑地恢复,所有修改都被逻辑地取消,但是数据结构以及数据库块本身在回滚后可能会改变。考虑到可能会有并发事务,必须这样。
-
Undo segment 是保存在表空间上的。Undo 大小是固定的,既然是固定的也就是有限的。如果保存的记录非常多,那么它就会被占满,新记录的数据会覆盖掉最早的数据。所以用一个圆形的盘片能更加形象的表示。数据从一个位置开始写入,当写满一圈后,最新的数据就会覆盖最早写入的数据。
-
UNDO也会受到REDO的保护。换句话说,会把UNDO数据当成是表数据或索引数据一样,对UNDO的修改会生成一些REDO,这些REDO将计入日志。
# undo可以做哪些事儿?
-
Transaction rollback(事务反转)
事务反转是人主动去做的,人在操作的过程中反悔了,相当于我在写文档时按个ctrl+z 。 -
Transaction recovery(事务恢复)
事务恢复是机器自动完成的,比如在事务进行过程中简拼突然断电了,下次重启服务之后,系统自动回滚。 -
Read consistency (读一致性)
读一致性对于多用户操作是非常重要的。如果你在多人开发中使用过版本控制工具(git\cvs\svn)的话,下面的概念你将很容易理解。
# Oracle 读一致性概念
我知道oracle允许可以由多个用户对数据库进行操作,当你执行一个查询几百万条记录的操作时,这个过程可能需要几分钟。在这个过程中其它用户对你查询的数据时行了修改。这里就要保证你查询的结果是被修改之前的。
这里明确一个概念,事务的开始,在我们执行一条(更新、修改、删除)语句时;事务的结束,必须执行提交动作(执行commit 或 rollback 命令)
我们从上面的流程图来理解一下oracle是如何保证读一致性的。
当我们执行一个事务的时候,oracle会分配一个SCN编号,这个编号是递增的。下一个事务的编号一定比当前事务的编号大。
上图中执行第一个事务分配的编号为10023,在这个事务执行的过程中,另一事务对SCN 编号为10008和10021的数据块进行了修改。用来替换的数据块SCN编号为10024 ,而被替换掉的数据块会被保存到undo segment上面。
当第一个事务(scn=10023)执行到被修改过的数据块时,发现10024比10023大,这个时候就会到undo segment上找比自己SCN号小的数据块进行读,于是发找到了SCN号为10008和10021两个块。这样就有效的保证了读一致性。如果找不到就报错:ORA-01555:snapshot too old 错误
当然,会有一种特殊情况,也就是undo segment 太小,最多放100条数据,可一下子来了120条数据,那么最先写入的20条数据被最后写入的20条数据覆盖。这个时候就会报错,这也是为什么要对数据据进行调优的原因。
# 对undo段的一个误解:物理恢复 or 逻辑恢复
通常对undo有一个误解,认为undo用 于数据库 物理地恢复 到执行语句或事务之前的样子,但实际上并非如此。数据库只是 逻辑地恢复 到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据库 块本身在回滚后可能大不相同。
(比如一个插入操作,新分配了一些数据块。后来事务失败,插入操作全部回滚,新分配的一些数据块还是存在的)
无法物理恢复(的原因在于…)
在所有多用户系统中,可能会有数十、数百甚至数千个并发事务。数据库的主要功能之一就是协调对数据的并发访问。 也许我们的事务在修改一些块,而一般来讲往往会有许多其他的事务也在修改这些块。因此,不能简单地将一个块放回到我们的事务开始前的样子,这样会撤销其他人 (其他事务)的工作!
例如:
假设我们的事务执行了一个INSERT语句,这条语句导致分配一个新区段(也就是说,导致表的空间增大)。通过执行这个INSET,我们将得到一个新的块,格式化这个块以便使用,并在其中放上一些数据。此时,可能出现另外某个事务,它也向这个块中插入数据。如果要回滚我们的事务,显然不能取消对这个块的格式化和空间分配。
因此,Oracle回滚时,它实际上会做与先前逻辑上相反的工作。 对于每个INSERT,Oracle会完成一个DELETE。对于每个DELETE,Oracle会执行一个INSERT。对于每个UPDATE,Oracle则会执行一个“反UPDATE“,或者执行另一个UPDATE将修改前的行放回去。
所以有一种异常情况就很容易解释了
一个表明明只有1000行左右的数据,一条select * from table
语句可能需要耗时1,2分钟。
这张表应该是经常进行新增删除操作的表比如
我新增了1000万行数据,然后又将这些数据删除。对这个表进行全表扫描的时候,仍然会去扫描这1000万行以前所占用的那些数据块,看看里面是否包含数据。也就是oracle里面所说的高水平线(HWM),这些数据块都增加到了高水平线下面,oracle会扫描所有高水平线下的数据块。
逻辑恢复的验证
undo在数据库内部存放在一组特殊的段中,为undo段(回滚段