(原)Oracle事务与Undo段的分配过程

我们都知道,Oracle在进行dml过程中,有重要的一步,即创建undo和redo。redo用于事务重演,而undo用于事务的回退。

创建undo,记录data block的前映像,需要在undo tablespace 中分配undo segment,来记录undo record。

最近一个oracle群里遇到一个事务引起undo tablespace的一个undo segment暴涨的情况,群里也进行了讨论,其中有Q友发出了oracle doc中关于dml事务

对undo segment 的分配和使用情况,如下:

群里讨论最后,我也来测试下这个过程及结论。

(1):准备工作

--创建一个新的undo tablespace,大小640k,数据文件禁止自动扩展,用于替换原来的undo tablespace.
--之前已经测试过一个初始的undo segment 大小为:128*1024=128k,这里指定这个数据文件大小:128k*5 = 640k
create undo  tablespace  undotbs5  DATAFILE 'E:/oradata/undotbs5.dbf'   SIZE 640k reuse autoextend off;

--切换回滚段: alter system set undo_tablespace=undotbs5 scope=both;
--把原来的undo 表空间离线,并删除(这里必须是原来的undo segment都要offline,才能删除undo tablespace)
alter tablespace undotbs1 offline;
drop tablespace undotbs1 including contents and datafiles;

(2):创建事务操作的测试表

create table test(
id number,
name varchar2(20));


begin
    for i in 1..20 loop
        insert into test(id,name) values(i,'sina' || i);
    end loop;
    commit;
end;
/

(3):查看目前undo tablespace的表空间及数据文件

--查看undo 表空间
col tablespace_name for a20
col status for a10
set lines 200
select tablespace_name,block_size,min_extents,max_extents,status,contents,extent_management,allocation_type from dba_tablespaces where contents='UNDO';

TABLESPACE_NAME      BLOCK_SIZE MIN_EXTENTS MAX_EXTENTS STATUS     CONTENTS           EXTENT_MANAGEMENT    ALLOCATION_TYPE
-------------------- ---------- ----------- ----------- ---------- ------------------ -------------------- ------------------
UNDOTBS5                   8192           1  2147483645 ONLINE     UNDO               LOCAL             SYSTEM


--查看undo segment
col segment_name for a30
select segment_name,segment_type,bytes/1024 from dba_segments where tablespace_name='UNDOTBS5';

SEGMENT_NAME                   SEGMENT_TYPE                         BYTES/1024
------------------------------ ------------------------------------ ----------
_SYSSMU5$                      TYPE2 UNDO                                  128
_SYSSMU6$                      TYPE2 UNDO                                  192
_SYSSMU7$                      TYPE2 UNDO                                  128
_SYSSMU8$                      TYPE2 UNDO                                  128

我们可以看到,此undo tablespace包括4个undo segment,一个undo segment段的初始物理大小为128k,其中_SYSSMU6$为192k. 


--查询undo表空间的数据文件,我们这里把这个数据文件大小固定,且不能自动扩展
col file_name for a40
col tablespace_name for a20
set lines 200
select file_name,tablespace_name,bytes/1024 size_kb,autoextensible,maxbytes/1024/1024,user_bytes/1024/1024 from dba_data_files where tablespace_name='UNDOTBS5';

FILE_NAME                                TABLESPACE_NAME         SIZE_KB AUTOEX MAXBYTES/1024/1024 USER_BYTES/1024/1024
---------------------------------------- -------------------- ---------- ------ ------------------ --------------------
E:\ORADATA\UNDOTBS5.DBF                  UNDOTBS5                    640 NO                      0        .5625

我们可以看到,undo tablespace只包括一个数据文件,且此数据文件大小 为640k,不能自动扩展。

 

(4):更改一个undo segment为offline状态

--查询目前undo tablespace 已经分配的所有的undo segment,我们可以看到online状态和offline状态的
set lines 200
col segment_name for a20
col tablespace_name for a20
col status for a10
select segment_id,segment_name,tablespace_name,file_id,min_extents,max_extents,status from dba_rollback_segs order by 1;

SEGMENT_ID SEGMENT_NAME         TABLESPACE_NAME         FILE_ID MIN_EXTENTS MAX_EXTENTS STATUS
---------- -------------------- -------------------- ---------- ----------- ----------- ----------
         0 SYSTEM               SYSTEM                        1           1       32765 ONLINE
         5 _SYSSMU5$            UNDOTBS5                      2           2       32765 ONLINE
         6 _SYSSMU6$            UNDOTBS5                      2           2       32765 ONLINE
         7 _SYSSMU7$            UNDOTBS5                      2           2       32765 ONLINE
         8 _SYSSMU8$            UNDOTBS5                      2           2       32765 ONLINE
         
我们看到,四个undo segment都是online,这里我们手工把一个undo segment改为offline状态

SQL> show user
USER 为 "SYS"
SQL> alter system set "_smu_debug_mode"=4;

系统已更改。

SQL> alter rollback segment "_SYSSMU8$" offline;

回退段已变更。

--再次查看
set lines 200
col segment_name for a20
col tablespace_name for a20
col status for a10
select segment_id,segment_name,tablespace_name,file_id,min_extents,max_extents,status from dba_rollback_segs order by 1;

SEGMENT_ID SEGMENT_NAME         TABLESPACE_NAME         FILE_ID MIN_EXTENTS MAX_EXTENTS STATUS
---------- -------------------- -------------------- ---------- ----------- ----------- ----------
         0 SYSTEM               SYSTEM                        1           1       32765 ONLINE
         5 _SYSSMU5$            UNDOTBS5                      2           2       32765 ONLINE
         6 _SYSSMU6$            UNDOTBS5                      2           2       32765 ONLINE
         7 _SYSSMU7$            UNDOTBS5                      2           2       32765 ONLINE
         8 _SYSSMU8$            UNDOTBS5                      2           2       32765 OFFLINE

我们看到 _SYSSMU8$ 的undo segment已经由online变成了offline.

--查询目前online的undo segment的状态。
--xacts不为0,表示该undo segment上有active的事务,如果>1,则说明有回滚段争用,需要增加回滚段数目。
set lines 200
col name for a25
col status for a10
select a.name, b.extents, b.rssize/1024/1024,b.xacts,b.waits,b.gets,b.optsize,b.status
from v$rollname a,v$rollstat b
where a.usn = b.usn;

NAME                         EXTENTS B.RSSIZE/1024/1024      XACTS      WAITS       GETS    OPTSIZE STATUS
------------------------- ---------- ------------------ ---------- ---------- ---------- ---------- ----------
SYSTEM                             6           .3671875          0          0         85            ONLINE
_SYSSMU5$                          3           .1796875          0          0       1967            ONLINE
_SYSSMU6$                          2           .1171875          0          0       2407            ONLINE
_SYSSMU7$                          2           .1171875          0          0       2301            ONLINE

此时没有_SYSSMU8$这个undo segment,上面我们已经手动让其offline。

(5):进行测试
--创建N个会话,同时执行update test表的操作,这时每个active session将会占用一个undo segment,如果online 的undo segment不够,刚先将offline的变成online来使用。如果offline的用完,则自动增加,一直到undo tablespace 没有空间(这里undo tablespace 只有一个数据文件,只有640k,所以很快就会被用完)。此时,每个undo segment里只有一个active的事务,如果此时还有事务,则根据一定算法,将已经含有acitve的undo segment里再分配一个active的事务,即一个undo segment里含有两个active状态的事务。

session1:
update test set name ='gogoxx' where id = 1;

session2:
update test set name ='gogoxx' where id = 2;

session3:
update test set name ='gogoxx' where id = 3;


在 session0 里查看:
set lines 200
col name for a25
col status for a10
select a.name, b.extents, b.rssize/1024/1024,b.xacts,b.waits,b.gets,b.optsize,b.status
from v$rollname a,v$rollstat b
where a.usn = b.usn;

NAME                         EXTENTS B.RSSIZE/1024/1024      XACTS      WAITS       GETS    OPTSIZE STATUS
------------------------- ---------- ------------------ ---------- ---------- ---------- ---------- ----------
SYSTEM                             6           .3671875          0          0         91            ONLINE
_SYSSMU5$                          3           .1796875          1          0       2262            ONLINE
_SYSSMU6$                          2           .1171875          1          0       2575            ONLINE
_SYSSMU7$                          2           .1171875          1          0       2581            ONLINE

只有三个segment处于online,且每个里面只有一个active的事务。
select segment_id,segment_name,tablespace_name,file_id,min_extents,max_extents,status from dba_rollback_segs order by 1; SEGMENT_ID SEGMENT_NAME TABLESPACE_NAME FILE_ID MIN_EXTENTS MAX_EXTENTS STATUS ---------- -------------------- -------------------- ---------- ----------- ----------- ---------- 0 SYSTEM SYSTEM 1 1 32765 ONLINE 5 _SYSSMU5$ UNDOTBS5 2 2 32765 ONLINE 6 _SYSSMU6$ UNDOTBS5 2 2 32765 ONLINE 7 _SYSSMU7$ UNDOTBS5 2 2 32765 ONLINE 8 _SYSSMU8$ UNDOTBS5 2 2 32765 OFFLINE 此时 _SYSSMU8$ 处于offline。

 

再执行session4:

update test set name ='gogoxx' where id = 4;

在 session0 里查看:
set lines 200
col name for a25
col status for a10
select a.name, b.extents, b.rssize/1024/1024,b.xacts,b.waits,b.gets,b.optsize,b.status
from v$rollname a,v$rollstat b
where a.usn = b.usn;

NAME                         EXTENTS B.RSSIZE/1024/1024      XACTS      WAITS       GETS    OPTSIZE STATUS
------------------------- ---------- ------------------ ---------- ---------- ---------- ---------- ----------
SYSTEM                             6           .3671875          0          0         97            ONLINE
_SYSSMU5$                          3           .1796875          1          0       2264            ONLINE
_SYSSMU6$                          2           .1171875          1          0       2577            ONLINE
_SYSSMU7$                          2           .1171875          1          0       2583            ONLINE
_SYSSMU8$                          2           .1171875          1          0       1864            ONLINE

此时_SYSSMU8$已经被online且包含了一个事务。

set lines 200
col segment_name for a20
col tablespace_name for a20
col status for a10
select segment_id,segment_name,tablespace_name,file_id,min_extents,max_extents,status from dba_rollback_segs order by 1;

SEGMENT_ID SEGMENT_NAME         TABLESPACE_NAME         FILE_ID MIN_EXTENTS MAX_EXTENTS STATUS
---------- -------------------- -------------------- ---------- ----------- ----------- ----------
         0 SYSTEM               SYSTEM                        1           1       32765 ONLINE
         5 _SYSSMU5$            UNDOTBS5                      2           2       32765 ONLINE
         6 _SYSSMU6$            UNDOTBS5                      2           2       32765 ONLINE
         7 _SYSSMU7$            UNDOTBS5                      2           2       32765 ONLINE
         8 _SYSSMU8$            UNDOTBS5                      2           2       32765 ONLINE

这里也显示_SYSSMU8$  由原来的offline变成了online.

执行 session5:

update test set name ='gogoxx' where id = 5;

在session 0里查看
set lines 200
col name for a25
col status for a10
select a.name, b.extents, b.rssize/1024/1024,b.xacts,b.waits,b.gets,b.optsize,b.status
from v$rollname a,v$rollstat b
where a.usn = b.usn;

NAME                         EXTENTS B.RSSIZE/1024/1024      XACTS      WAITS       GETS    OPTSIZE STATUS
------------------------- ---------- ------------------ ---------- ---------- ---------- ---------- --------
SYSTEM                             6           .3671875          0          0         65            ONLINE
_SYSSMU5$                          2           .1171875          1          0         71            ONLINE
_SYSSMU6$                          3           .1796875          2          0         87            ONLINE
_SYSSMU7$                          2           .1171875          1          0         87            ONLINE
_SYSSMU8$                          2           .1171875          1          0        130            ONLINE

我们此时看到 _SYSSMU6$ 的XACTS字段里的1变成了2,即此时,这个undo segment里已经有两个active的事务,说明,此时undo segment已经出现了争用。

 

由上证明了oracle doc里关于undo segment分配与事务的关系,这下关于undo 也搞得更清楚一点了。

Oracle、Linux、Unix
原文地址:https://www.cnblogs.com/taowang2016/p/3101544.html