01
web
作错事情的时候,咱们常常对本身说的最多的一句话就是:要是当时不这么作就行了,要是能复原就行了。现实中没有后悔药,oracle中有后悔药,这个后悔药就是undo。
sql
02数据库
咱们对数据执行修改时,数据库会生成undo信息,以便未来须要的时候能够把数据变动回修改以前的状态。此外,当你执行的事务或语句因为某种缘由失败的时候,或者你用一条rollback语句请求回滚时,oracle也须要利用这些undo信息将数据恢复到修改以前的样子。undo用于取消一条语句或一组语句的做用,它是存储在数据库内部一组特殊的段中,称为undo段。数据结构
03oracle
undo会将数据库“物理地”恢复到某个语句或事务以前的样子吗?咱们例子探究下:
app
而后查询这个表,咱们在slqplus中启用AUTOTRACE,它会报告I/O使用状况。ide
因为延迟段建立特性,能够看到对表的I/O数为零。所谓的延迟段建立,就是咱们在执行create table命令时,数据库不会分配任何存储空间,一个extents也不会。分配空间的动做会延迟到第一个insert动做,此时数据库才会真正建立段。
spa
insert语句会致使Oracle数据库为表t分配更多的数据库,当执行rollback命令时,这些新分配的数据块没有由于回滚而消失,它们还在那里,并且已经格式化(这和Linux中挂载盘有类似性),只不过如今为空。当咱们进行第二次全表扫描时,Oracle必须读取这些block,看看其中是否包含数据。orm
04事务
下面咱们指定延迟段建立表:
sql>drop table t purge;
Table dropped;
sql>CREATE TABLE t(x int) SEGMENT CREATION DEFERRED;
Table created;
SQL>select extent_id,bytes,blocks from user_extents where segment_name='T' order by extent_id;
no rows selected;
SQL>insert into t(x) values (1);
1 row created.
SQL>rollback;
Rollback complete.
SQL>select extent_id,bytes,blocks from user_extents where segment_name='T' order by extent_id;
EXTENT_ID BYTES BLOCKS
---------- ---------- ----------
0 65536 8
在此能够看到,表建立以后没有分配任何存储空间-----这个表没有任何extents。当咱们执行insert并紧接着执行rollback以后,能够看到insert确实分配了存储空间,不过rollback并无将分配的存储空间“释放”。
由此能够看出,segment确实由insert建立可是未被rollback" 撤销";另外一方面,由insert新建立的块会被第二次查询扫描。所以"后悔药"undo是逻辑地将数据恢复到原来的样子,某些修改会被"逻辑地"取消,可是数据结构以及数据块自己在回滚后可能(与事务或语句开始以前的数据块状态)大不相同