undo表空间中undo段是自动生成的,oracle自动使用undo表空间的undo段。
作为高级DBA,需要了解Oracle是如何使用undo段的。这样出了性能问题才能够解决。
1.Undo表空间及管理方式
SYS ASSYSDBA@ORCL>show parameter undo_tablespace;
NAME TYPE VALUE
------------------------------------ --------------------------------------------------
undo_tablespace string UNDOTBS1
SYS ASSYSDBA@ORCL>show parameter undo;
NAME TYPE VALUE
undo_management string AUTO #undo表空间自动管理
undo_retention integer 1000
undo_tablespace string UNDOTBS1 #undo表空间的名称
Undo 表空间的段,区,块都是自动生成和自动维护的。Oracle自动使用undo段。
Undo段
Undo段的名称:
SYS AS SYSDBA@ORCL>select* from v$rollname;
USN NAME
---------- --------------------
0SYSTEM #这个段在系统表空间中,
#有两个情况会使用系统表空间:
1.当对数据库对象(数据字典)修改时,会使用system表空间
2.当undo表空间坏了,会使用system表空间
1_SYSSMU1_592353410$ #这下面10个段在UNDOTBS1表空间中,段是自动调整的。
2 _SYSSMU2_967517682$
3 _SYSSMU3_1204390606$
4 _SYSSMU4_1003442803$
5 _SYSSMU5_538557934$
6 _SYSSMU6_2897970769$
7 _SYSSMU7_3517345427$
8 _SYSSMU8_3901294357$
9 _SYSSMU9_1735643689$
10_SYSSMU10_4131489474$
具体查看某个段的使用情况:
SYS AS SYSDBA@ORCL>select SEGMENT_NAME,BLOCKS,EXTENTSfrom dba_segments where SEGMENT_NAME='_SYSSMU9_1735643689$';
SEGMENT_NAME BLOCKS EXTENTS
_SYSSMU9_1735643689$ 272 4
查看undo段对应的区的详细信息:
SYS AS SYSDBA@ORCL>selectSEGMENT_NAME,TABLESPACE_NAME,EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS from dba_extentswhere SEGMENT_NAME='_SYSSMU9_1735643689$';
SEGMENT_NAME TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
_SYSSMU9_1735643689$ UNDOTBS1 0 3 256 8
_SYSSMU9_1735643689$ UNDOTBS1 1 3 200 8
_SYSSMU9_1735643689$ UNDOTBS1 2 3 11264 128
_SYSSMU9_1735643689$ UNDOTBS1 3 3 11392 128
结论:undo段的分配的区不是连续的,但分配的区内的块是连续的。
查看undo段的所属对象:
SYS AS SYSDBA@ORCL>select owner, segment_name,tablespace_name from dba_rollback_segs;
OWNER SEGMENT_NAME TABLESPACE_NAME
SYS SYSTEM SYSTEM
PUBLIC _SYSSMU10_4131489474$ UNDOTBS1
PUBLIC _SYSSMU9_1735643689$ UNDOTBS1
PUBLIC _SYSSMU8_3901294357$ UNDOTBS1
PUBLIC _SYSSMU7_3517345427$ UNDOTBS1
PUBLIC _SYSSMU6_2897970769$ UNDOTBS1
PUBLIC _SYSSMU5_538557934$ UNDOTBS1
PUBLIC _SYSSMU4_1003442803$ UNDOTBS1
PUBLIC _SYSSMU3_1204390606$ UNDOTBS1
PUBLIC _SYSSMU2_967517682$ UNDOTBS1
PUBLIC _SYSSMU1_592353410$ UNDOTBS1
SYS ASSYSDBA@ORCL>select name from v$parameter where name like '%undo%';
NAME
undo_management
undo_tablespace
undo_retention
UNDO表空间占用空间情况以及数据文件存放位置:
SYS AS SYSDBA@ORCL>select file_name,bytes/1024/1024from dba_data_files where tablespace_name like '%UNDOTBS%';
FILE_NAME BYTES/1024/1024
-----------------------------------------------------------------
/u01/app/oracle/oradata/ORCL/undotbs01.dbf 290
/u01/app/oracle/oradata/ORCL/undotbs02.dbf 10
undo的三个作用:
①事物回滚(rollback):
当执行一个事务时,oracle会将修改前的数据的行放到undo表空间中undo段中。当一个事务修改的数据越多,需要的undo段也就越多。
手动回滚:当执行一个事务没有提交前,发现有一条语句执行错了,这时就可以通过rollback手动回滚。
自动回滚:当执行一个事务还没有完成,执行这个事务的会话死了,这个事务需要自动回滚。
②读一致性,构造CR块
一个会话的未提交事务前修改的行,另一个会话是不可见的。从而保证读到的数据一定是提交后的数据。
当一个会话读到了一个被修改的行,而且还没有提交时,这个会话会在buffer cache里申请一个数据块,将需要读的数据对应的UNDO段写到这个数据块中。再读这个数据块。这个数据块叫CR块。这样通过构造CR块来确保读一致性。
③实例恢复,回滚未提交事物
实例恢复分两部:
前滚:通过redo log将所有的脏块在buffer cache中构造出来
回滚:将未提交的事物对应的脏块进行回滚
Undo段中区的四种状态:
free #如何区没有分配给任何段,这个区就是free
expired #已提交事务的区会保持一段时间,这个时间由参数undo_retention(秒)配置。这个时间过后,这个区就会变成expired(过期),也代表这个区可以重用被覆盖了。
inactive #当这个事务提交后,这个区的状态就是inactive,一般来会覆盖。
active #这个区被一个事务所使用,这个事务还没有提交,这个区的状态就是active.
一个事务申请undo表空间的流程:
Free->扩undo表空间->使用expired->inactive->如果还不够,会话会死掉,事务会被回滚。
查看UNDOSegment的状态:
SYS AS SYSDBA@ORCL>SELECT extent_id, bytes, statusFROM dba_undo_extents WHERE segment_name='_SYSSMU9_1735643689$';
EXTENT_IDBYTES STATUS
---------- ---------- ----------
0 65536 EXPIRED
1 65536 EXPIRED
2 1048576 EXPIRED
3 1048576 UNEXPIRED
SYS ASSYSDBA@ORCL>Selectusn,xacts,rssize/1024/1024/1024,hwmsize/1024/1024/1024,shrinks from v$rollstatorder by rssize;
USNXACTSRSSIZE/1024/1024/1024 HWMSIZE/1024/1024/1024 SHRINKS
-------------------- --------------------- ---------------------- ----------
0 0 .000358582 .000358582 0
9 0 .002067566 .002067566 0
2 0 .002067566 .002067566 0
7 0 .002067566 .002067566 0
10 0 .002067566 .002067566 0
5 0 .002250671 .002250671 0
6 0 .003044128 .003044128 0
3 0 .003044128 .003044128 0
8 0 .003044128 .003044128 0
4 0 .003044128 .003044128 0
1 0 .004020691 .004020691 0
undo_retention (undo段中区状态为inactive状态的保留时间)
下面参数作用主要是对于undo段中区的状态为inactive状态的覆盖处理方式:
guarantee为强制保留,表示在undo_retention时长内,inactive状态的区不会被覆盖。
修改方式:
alter tablespace undotbs1 retention guarantee; #修改
alter tablespace undotbs1 retention noguarantee; #修改回默认值
查看修改是否成功:
SYS ASSYSDBA@ORCL>select TABLESPACE_NAME,RETENTION from dba_tablespaces WHERE TABLESPACE_NAME='UNDOTBS1';
TABLESPACE_NAME RETENTION
-------------------- --------------------
UNDOTBS1 GUARANTEE
2.图解一个事物的操作流程:
select xid, xidusn, xidslot, xidsqn, ubablk, ubafil fromv$transaction;
----
小结:
ITL中UBA指向data block的最后一个undo block地址,undo block之间指向,都是为了回滚操作;
Data block header 与Undoblock的直接指向,为了构造cr块更快速;
ITL中XID指向undo segment header是为了多种提交方式。
一个事物开始之后,至少要在两个位置写入事物信息:
1.回滚段的段头块的事物表中
2.要修改的数据块的头部事物槽的位置,找一个事物槽,将事物信息写上。
3.IMU机制
传统的undo,oracle将undo表空间和普通表空间同等对待。
而现在,有了IMU技术,事物开始以后,需要回滚块的时候不再需要从磁盘调取,直接在shared pool中IMU buffer中读取。
IMU大幅提高了构造cr块的速度,从而也提高了cr读的速度。
RAC和Stream环境中,IMU是被禁止掉的。
而且,IMU技术目前没有被Oracle大肆宣扬。
1 | select * from v$sysstat where name like '%IMU%'; |
--上面sql查询的结果可以判断IMU是否开启,关注查询结果中IMU commits和IMU Flushes 的value,如果一直在增加,说明数据库开启了IMU技术。
4.读一致性
举个例子:
9:00开始查询一个1w条返回记录的表。
9:01其他用户删除了第1w条记录,并提交。
9:02查询结束,返回结果应该是1w条还是9999条?
按照之前所学的知识,可能就是9999条了,但是实际上oracle返回的是1w条记录,这也是根据业务实际要求的。
引入新的知识点:查询的时候会先对当前状态进行快照,记录一个当前scn,就是说之后查询过程中如果发现有块的scn号大于当前scn,就说明这个块在查询过程中被修改了。
ORA-01555
1.sql 执行的时间太长;
2.undo 表空间的压力太大;
3.undo 表空间大小的设定,取决于最长执行sql的时间,以及需要闪回的时段。然后根据这些具体的需求在em中undo表空间的建议图中根据时间找到对应的undo表空间应该设置为多大的参考值。