一文了解清楚oracle数据库undo表空间
undo表空间对于oracle数据库至关重要,在数据库使用期间,undo表空间能够确保保障事务的读一致性,实现事务的回滚和恢复。
一、undo的作用
1.1,读一致性
我们读取某个表数据时,如某一个回话正在修改某一条数据,我们读取到的实际还是更改前的数据(这只是其中的一种形式,这里面还涉及到数据库隔离级别,我们就不展开讨论了),而其中数据的读取一致性,就是通过undo回滚段实现的。
我们打开两个回话,其中一个回话进行数据修改而不提交,另外一个回话同时查询,可以看到数据修改前后查到的数据一致。
修改前查询:
SQL> select * from vehicle;
HPHM HPZL SYR
-------- ---------- ------------------------------------------------------------
湘A00000 02 湖南长沙
湘A00001 02 湖南长沙
湘A00002 02 湖南长沙
湘A00003 02 湖南长沙
湘A00004 02 湖南长沙
湘A00005 02 湖南长沙
湘A00006 02 湖南长沙
7 rows selected.
我们修改第一条数据,不提交然后在第一个窗口查询数据(可以看到数据还是未改变)
SQL> update vehicle set hpzl='01' where hphm like '%A00000';
1 row updated.
SQL> select * from vehicle;
HPHM HPZL SYR
-------- ---------- ------------------------------------------------------------
湘A00000 02 湖南长沙
湘A00001 02 湖南长沙
湘A00002 02 湖南长沙
湘A00003 02 湖南长沙
湘A00004 02 湖南长沙
湘A00005 02 湖南长沙
湘A00006 02 湖南长沙
7 rows selected.
1.2,事务回滚和恢复
我们修改某些数据的时候,如果我们突然不想操作了,需要进行回退,那么也需要undo表空间的回滚段。undo回滚段会在事务进行更新时候进行块的复制,更新并记录相关日志,如果需要回退,则根据日志信息利用回滚段数据进行回滚。
我们同一个窗口更新某一行数据:
SQL> select * from vehicle;
HPHM HPZL SYR
-------- ---------- ------------------------------------------------------------
湘A00000 02 湖南长沙
湘A00001 02 湖南长沙
湘A00002 02 湖南长沙
湘A00003 02 湖南长沙
湘A00004 02 湖南长沙
湘A00005 02 湖南长沙
湘A00006 02 湖南长沙
7 rows selected.
SQL> update vehicle set hpzl='01' where hphm like '%A00000';
1 row updated.
同一个回话查询数据:
SQL> select * from vehicle;
HPHM HP SYR
-------- -- ------------------------------------------------------------
湘A00000 01 湖南长沙
湘A00001 02 湖南长沙
湘A00002 02 湖南长沙
湘A00003 02 湖南长沙
湘A00004 02 湖南长沙
湘A00005 02 湖南长沙
湘A00006 02 湖南长沙
7 rows selected.
回滚再查询数据,发现数据又跟操作前一样了:
SQL> rollback;
Rollback complete.
SQL> select * from vehicle;
HPHM HP SYR
-------- -- ------------------------------------------------------------
湘A00000 02 湖南长沙
湘A00001 02 湖南长沙
湘A00002 02 湖南长沙
湘A00003 02 湖南长沙
湘A00004 02 湖南长沙
湘A00005 02 湖南长沙
湘A00006 02 湖南长沙
7 rows selected.
二、undo参数
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
2.1,管理模式
Oracle 的Undo有两种方式, 一是使用undo 表空间,二是使用回滚段。
我们通过 undo_management 参数来控制使用哪种方式,如果设为auto,就使用UNDO 表空间,这时必须要指定一个UNDO 表空间。 如果设为manual,系统启动后使用rollback segment方式存储undo信息。如果系统没有指定undo_management,那么系统默认以manual方式启动,即使设置了auto方式的参数,这些参数将被忽略。
当实例启动的时候,系统自动选择第一个有效的undo表空间或者是rollback segment,如果没有有效的可用的undo表空间或者是回滚段,系统使用system rollback segment。这种情况是不被推荐的,当系统运行在没有undo的情况下,系统会在alert.log中记录一条警告信息。
2.2,undo保留规则
UNDO_RETENTION,该参数用来指定undo 记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改,通常默认是900 秒,也就是15 分钟。
undo_retention 只是指定undo 数据的过期时间,并不是说,undo 中的数据一定会在undo表空间中保存15 分钟,比如说刚一个新事务开始的时候,如果undo 表空间已经被写满,则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期,因此呢,这就又关联回了第一点,当你创建一个自动管理的undo 表空间时,还要注意其空间大小,要尽可能保证undo 表空间有足够的存储空间。
undo_retention 中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被flashback 特性引用。如果你的undo表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention 参数的值并不会影响到你,哪怕你设置成1,只要没有事务去覆盖undo 数据,它就会持续有效。因此呢,这里还是那句话,要注意undo 表空间的大小,保证其有足够的存储空间。
只有在一种情况下,undo 表空间能够确保undo 中的数据在undo_retention 指定时间过期前一定有效,就是为undo 表空间指定Retention Guarantee,指定之后,oracle 对于undo 表空间中未过期的undo 数据不会覆盖,例如:
SQL> Alter tablespace undotbs1 retention guarantee;
三、undo操作
3.1,undo表空间切换
建立新的undo表空间
SQL> CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE '/oracle/oradata/orcl/undo03.dbf' size 100M reuse;
表空间已创建。
切换到新的undo表空间上来
SQL> alter system set undo_tablespace=UNDOTBS2 scope=both;
系统已更改。
将原理的undo表空间下线
SQL> alter tablespace UNDOTBS1 offline;
表空间已更改。
删除下线的undo表空间
SQL> drop tablespace UNDOTBS1 including contents AND DATAFILES CASCADE CONSTRAINTS ;
表空间已删除。
3.2,undo表空间损坏恢复
有些时候我们undo表空间损坏,数据库启动过程中就会报错:
ORA-01157: cannot identify/lock data file 12 - see DBWR trace file
ORA-01110: data file 12: '/oracle/oradata/orcl/undotbs01.dbf'
因为undo表空间损坏,导致我们不能够开启数据库,但是数据库不能够open,我们又不能新增undo表空间。对此,我们只能先修改参数,让数据库使用默认的system表空间来使用undo回滚段。
创建pfile文件(同时也是备份下参数文件)
SQL> create pfile='/oracle/pfilebak.ora' from spfile;
文件已创建。
修改pfile文件
#*.undo_tablespace='UNDOTBS1'
#*.undo_management='AUTO'
undo_management='MANUAL'
rollback_segments='SYSTEM'
启动数据库到mount阶段
SQL> STARTUP MOUNT pfile='/oracle/pfilebak.ora' ;
offline drop掉损坏的undo表空间
SQL> ALTER DATABASE DATAFILE '/oracle/oradata/orcl/undotbs01.DBF' OFFLINE DROP;
开启数据库
SQL> ALTER DATABASE OPEN;
删除旧的undo表空间,创建新的undo表空间
DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS;
SQL> create undo tablespace undotbs2 datafile '/oracle/oradata/orcl/undotbs02.DBF' size 100M;
表空间已创建。
关闭数据库,修改参数文件,指定undo表空间为undotbs2
SQL> shutdown immediate
*.undo_tablespace='UNDOTBS2'
*.undo_management='AUTO'
#undo_management='MANUAL'
#rollback_segments='SYSTEM'
启动到nomount阶段,进行参数文件spfile的修改,用spfile启动
SQL> startup nomount pfile='/oracle/pfilebak.ora' ;
SQL> create spfile from pfile='/oracle/pfilebak.ora';
停止数据库,启动数据库
SQL> shutdown immediate
SQL> startup