查询数据库中所有的undo表空间。
SQL> select tablespace_name from dba_tablespaces where contents='UNDO' ;
TABLESPACE_NAME
------------------------------
UNDOTBS1
创建一个undo表空间
SQL> create undo tablespace undotbs2 datafile '/u01/app/oracle/oradata/WH/undot
s2.dbf'> Tablespace created.
SQL> select tablespace_name from dba_tablespaces where contents='UNDO' ;
TABLESPACE_NAME
------------------------------
UNDOTBS1
UNDOTBS2
查询数据库字典dba_sgement,undo段的信息
SQL> select * from dba_segments where tablespace_name in ('UNDOTBS1','UNDOTBS2')
一共有20个undo段,undotbs1和undotbs2各10个,每个段默认最小有2个extended
查询数据库字典dba_rollback_segs,可以看出udotbs1的回滚段都是处于online状态,undotbs2的回滚段处于offline状态
SQL> col segment_name format a30;
SQL> col tablespace_name format a15;
SQL> select segment_name,owner,tablespace_name,status from dba_rollback_segs;
SEGMENT_NAME OWNER TABLESPACE_NAME STATUS
------------------------------ ------ --------------- ----------
SYSTEM SYS SYSTEM ONLINE
_SYSSMU10_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU9_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU8_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU7_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU6_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU5_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU4_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU3_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU2_1186132793$ PUBLIC UNDOTBS1 ONLINE
_SYSSMU1_1186132793$ PUBLIC UNDOTBS1 ONLINE
SEGMENT_NAME OWNER TABLESPACE_NAME STATUS
------------------------------ ------ --------------- ----------
_SYSSMU20_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU19_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU18_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU17_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU16_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU15_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU14_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU13_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU12_1367581872$ PUBLIC UNDOTBS2 OFFLINE
_SYSSMU11_1367581872$ PUBLIC UNDOTBS2 OFFLINE
21 rows selected.
从参数undo_tablespace中可以看出当前数据库使用的undo表空间是undotbs1。
SQL> show parameter undo_tablespace;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDOTBS1
SQL>
改变uodo表空间为undotbs2,
SQL>>
System> SQL> show parameter undo_tablespace;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDOTBS2
SQL> select segment_name,owner,tablespace_name,status from dba_rollback_segs;
SEGMENT_NAME OWNER TABLESPACE_NAME STATUS
------------------------------ ------ --------------- ----------------
SYSTEM SYS SYSTEM ONLINE
_SYSSMU10_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU9_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU8_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU7_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU6_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU5_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU4_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU3_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU2_1186132793$ PUBLIC UNDOTBS1 OFFLINE
_SYSSMU1_1186132793$ PUBLIC UNDOTBS1 OFFLINE
SEGMENT_NAME OWNER TABLESPACE_NAME STATUS
------------------------------ ------ --------------- ----------------
_SYSSMU20_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU19_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU18_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU17_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU16_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU15_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU14_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU13_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU12_1367581872$ PUBLIC UNDOTBS2 ONLINE
_SYSSMU11_1367581872$ PUBLIC UNDOTBS2 ONLINE
21 rows selected.
然后再查询dba_rollback_segs,发现uodotbs的回滚段全部online了,而undotb1的回滚段变为了offline状态。
从前面实验可知一个实例可以创建多个undo表空间,但是一个实例只能使用一个undo表空间,不能同时让所有undo表空间的回滚段同时online。每个实例都会有个段名为system,所有者sys,并且属于system表空间的回滚段,其它回滚段的owner都为public,表名system回滚段是私有的,其它的回滚段可以让多个实例(RAC)共用
通过下面实验理解oracle是如何通过undo保证数据库读一致性
创建表test,并且插入2行数据提交
SQL> create table test (id int, name varchar2(10));
Table created.
SQL> insert into test values (1,'a');
1 row created.
SQL> insert into test values (2,'b');
1 row created.
SQL> commit;
Commit complete.
现在更新表test的一个字段值,不commit
SQL> select * from test;
ID NAME
---------- ----------
1 a
2 b
SQL> update test set name='abc' where> 1 row updated.
再执行查询看到已经更改过来
SQL> select * from test;
ID NAME
---------- ----------
1 abc
2 b
开启另外一个session再查询表test
C:\>sqlplus sys/oracle@DGWH as sysdba
SQL*Plus:> Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition> With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> select * from test;
ID NAME
---------- ----------
1 a
2 b
然后查询v$transaction视图,发现有一个活动的事物,可知在为commit之前数据还是以前的状态,那么这时候的数据就是从undo里面读出来的
根据rowid可知这两行数据库都位于文件编号为1,块编号为86626的数据块中
SQL> select> _block_number(rowid) bno from test;
ID NAME FNO BNO
---------- ---------- ---------- ----------
1 abc 1 86626
2 b 1 86626
将块编号为86626从内存中dump出来分析,dump出来的文件存放在background_dump_dest指定的目录中,以时间降序排列即可找到这个文件,若不确定是哪个该文件,由于文件名中包含该session的进程id,可以根据进程id找到。
SQL>>
System> SQL> show parameter background_dump_dest;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
background_dump_dest string /u01/app/oracle/diag/rdbms/wh/
WH/trace
SQL>
下面列出了dump文件中的关键信息
Block header dump: 0x00415262