Undo表空间的设置和监控策略

Undo表空间的设置和监控策略

转自:https://www.modb.pro/db/1810135249725173760

1、发现问题

某套数据库的环境的undo表空间的使用率一直在超过监控的85%,一直报警一直扩容还在一直报警,甚至超过了业务表空间的大小,需要我们确认他是否真的需要这么大的空间?多大的空间能够保证数据库可以正常使用?undo表空间的使用机制到底是什么样的?

1.1、数据库环境

select a.tablespace_name,

round(a.bytes / 1024 / 1024 / 1024, 0) "sum G",

round((a.bytes - b.bytes) / 1024 / 1024 / 1024, 0) "used G",

round(b.bytes / 1024 / 1024 / 1024, 0) "free G",

round(((a.bytes - b.bytes) / a.bytes) * 100, 2) "used%"

from (select tablespace_name, sum(bytes) bytes

from dba_data_files

group by tablespace_name) a,

(select tablespace_name, sum(bytes) bytes, max(bytes) largest

from dba_free_space

group by tablespace_name) b

where a.tablespace_name = b.tablespace_name and a.tablespace_name in ('UNDOTBS1','UNDOTBS2')

order by ((a.bytes - b.bytes) / a.bytes) desc;

##########################################################################

TABLESPACE_NAME sum G used G free G used%

1 UNDOTBS2 150 132 18 87.8

2 UNDOTBS1 156 130 26 83.57

2、定位问题

2.1、涉及的视图或者参数

SQL> show parameter undo

NAME TYPE VALUE

------------------ ----------- ----------------

_gc_undo_affinity boolean FALSE

undo_management string AUTO

undo_retention integer 900

undo_tablespace string UNDOTBS1

select * from dba_views where view_name like '%UNDO%';

OWNER VIEW_NAME

1 SYS V_$UNDOSTAT

4 SYS GV_$UNDOSTAT

3 SYS DBA_UNDO_EXTENTS

2 SYS DBA_HIST_UNDOSTAT

挑几个重要的来解答:

undo_retention决定了撤销保留的时间,单位是秒。

DBA_UNDO_EXTENTS的status列有三种状态,分别是active(正在使用,无法覆盖)、unexpired(未过期,未超过由undo_retention设置的时间),expired(过期,超过了undo_retention设置的时间)。

undo表空间是可以循环使用的表空间,使用顺序是Free(未分配) - expired(过期) - unexpired(未过期) - active(报错,空间不足)。只要在某个时间段undo提供的表空间大于acive状态下的数据量,那么undo就不会报错。

V$UNDOSTAT十分钟记录一条,只会记录576条,接近四天时间的Undo信息,而DBA_HIST_UNDOSTAT则把超过四天时间的信息记录下来,接近10天左右。所以DBA_HIST_UNDOSTAT其实主要是V$UNDOSTAT的延申。而这两个视图是都可以记录undo在某段时间里的undo空间大小。

3、解决问题

3.1、显示过期时间

NAME TYPE VALUE

---------------- ----------- ----------

undo_retention integer 900

3.2、判断思路

那么在这种情况下,该怎么才能保证Undo够用呢?

第一种情况,保证undo_retention的使用时间,可以在过期时间内及时回退,并且使用率85%以下(70%最好),这个是最优。

第二种情况,保证Undo表空间能正常使用,不必在乎他使用率多少,能正常使用就行。(但是这个不能监控。)

第三种情况,Undo空间不足,导致数据没法对外提供服务。

3.2.1、最高等,保证正常使用的情况下还能及时恢复被误删的数据

select tablespace_name, status, round(sum(bytes/1024/1024/1024),2) "GB"

from dba_undo_extents

group by tablespace_name, status

order by 1, 2;

TABLESPACE_NAME STATUS GB

1 UNDOTBS1 ACTIVE 0.95

2 UNDOTBS1 EXPIRED 15.37

3 UNDOTBS1 UNEXPIRED 108.97

4 UNDOTBS2 ACTIVE 0.28

5 UNDOTBS2 EXPIRED 42.93

6 UNDOTBS2 UNEXPIRED 82.09

保证回滚段状态是 ACTIVE 和 UNEXPIRED的正常使用。就能大概计算出undo表空间的最高使用保证。

3.2.2、满足使用

select ur undo_retention,

dbs db_block_size,

round(((ur * (ups * dbs)) + (dbs * 24)) / 1024 / 1024,2) as "M_bytes"

from (select value as ur from v$parameter where name = 'undo_retention'),

(select (sum(undoblks) / sum(((end_time - begin_time) * 86400))) ups

from v$undostat),

(select value as dbs from v$parameter where name = 'db_block_size');

UNDO_RETENTION DB_BLOCK_SIZE M_bytes

1 900 8192 1055.57

ups: 这是撤销块的使用率,计算公式为undoblks(撤销块的数量)除以时间差(end_time - begin_time,单位为秒)乘以86400(转换为天)。

(ur * (ups * dbs)): 这是基于撤销保留时间、撤销块使用率和数据库块大小计算的撤销空间大小(以字节为单位)。

(ur * (ups * dbs)) + (dbs * 24): 加上24小时的数据库块大小,可能是为了考虑额外的撤销空间需求。

这个计算公式是算了七天的平均量,我有个很夸张的想法,我要是真的在生产库,就给他两G的undo表空间,禁止自增,是不是也是够用的?

select ur undo_retention,

dbs db_block_size,

round(((ur * (ups * dbs)) + (dbs * 24)) / 1024 / 1024,2) as "M_bytes"

from (select value as ur from v$parameter where name = 'undo_retention'),

(select (undoblks / ((end_time - begin_time) * 86400)) ups

from v$undostat

where undoblks in (select max(undoblks) from v$undostat)),

(select value as dbs from v$parameter where name = 'db_block_size');

UNDO_RETENTION DB_BLOCK_SIZE M_bytes

1 900 8192 4658.81

从v$undostat中计算撤销块的使用率(ups),这是通过将最大撤销块数量除以时间段(以天为单位)来计算的。

最后,计算撤销空间使用情况,公式为((ur * (ups * dbs)) + (dbs * 24)) / 1024 / 1024,其中ur是撤销保留时间,ups是撤销块使用率,dbs是数据库块大小,dbs * 24可能代表一天内额外的块需求。

很显然不是,因为七天中最高的undo使用峰值,超过了2G,虽然也就差不多4G,为了避免不够用,5G是绰绰有余的。

3.2.3、无法满足使用

如果undo表空间的没有超过回滚段峰值,也没有保证在(undo表空间GUARANTEE状态下)active和unexpired的数据量大小总值。那就会报空间不足。

题外话:undo表空间的GUARANTEE状态是保证只有expired的回滚段才会覆盖,active和unpired状态的数据是不会被覆盖的,能够保证undo_retention时间内的DML数据回退。

缺省情况下,undo表空间的状态时NOGUARANTEE,是可以覆盖unpired的数据。

4、验证问题

4.1、undo_retention时间过后是否释放

记录测试库本身回滚段信息

SQL> select owner,round(sum(bytes)/1024/1024,2) as MB,status from DBA_UNDO_EXTENTS group by owner,status;

OWN MB STATUS

--- ---------- ---------

SYS .56 EXPIRED

SYS 118.38 UNEXPIRED

设置撤销保留时间为10秒

SQL> alter system set undo_retention = 10 scope=both;

System altered.

查看是否修改成功

SQL> show parameter undo_retention

NAME TYPE VALUE

-------------- ----------- -------

undo_retention integer 10

压测插入数据

SQL> begin

for i in 1..1000000 loop

insert into t_tx values(i,mod(i,10));

end loop;

commit;

end;

/

过一分钟(其实十秒就行)查看回滚段信息

SQL> select owner,round(sum(bytes)/1024/1024,2) as MB,status from DBA_UNDO_EXTENTS group by owner,status;

OWN MB STATUS

--- ---------- ---------

SYS 50.75 EXPIRED

SYS 68.25 UNEXPIRED

随着时间的推移,回滚段的数据的确是释放,但是状态只有EXPIRED和UNEXPIRED,没有Free的说法。也就是说此时再看,Undo表空间的使用率是100%。

4.2、undo是否将状态是EXPIRED、UNEXPIRED都能使用

限制undo表空间大小并关闭自增

SQL> alter database datafile '/u01/app/oracle/oradata/orcl/undotbs01.dbf' resize 120M;

SQL> alter database datafile '/u01/app/oracle/oradata/orcl/undotbs01.dbf' autoextend off;

查看undo表空间的限制信息

SQL> set pages 999 lines 999

SQL> col file_name for a60

SQL> select file_name,tablespace_name,bytes/1024/1024 from dba_data_files where tablespace_name='UNDOTBS1';

FILE_NAME TABLESPACE_NAME BYTES/1024/1024

-------------------------------------------- ----------------- ---------------

/u01/app/oracle/oradata/orcl/undotbs01.dbf UNDOTBS1 120

创建测试用户

SQL> create user test identified by test default tablespace users;

SQL> grant connect,resource,dba to test;

查看现在的undo信息

select owner,round(sum(bytes)/1024/1024,2) as MB,status from DBA_UNDO_EXTENTS group by owner,status;

OWN MB STATUS

--- ---------- ---------

SYS 7.38 EXPIRED

SYS 92.25 UNEXPIRED

开始压测,要找到能一口气压测报错的数据量大小

conn test/test

##创建表

create table t_tx (id number,name varchar2(64));

##插入数据

begin

for i in 1..2000000 loop

insert into t_tx values(i,mod(i,10));

end loop;

commit;

end;

/

ERROR at line 1:

ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS1'

ORA-06512: at line 3

查看此时的undo表空间信息,我这里undo表空间如果满了就不会显示使用率。

select a.tablespace_name,

round(a.bytes / 1024 / 1024 / 1024, 0) "sum G",

round((a.bytes - b.bytes) / 1024 / 1024 / 1024, 0) "used G",

round(b.bytes / 1024 / 1024 / 1024, 0) "free G",

round(((a.bytes - b.bytes) / a.bytes) * 100, 2) "used%"

from (select tablespace_name, sum(bytes) bytes

from dba_data_files

group by tablespace_name) a,

(select tablespace_name, sum(bytes) bytes, max(bytes) largest

from dba_free_space

group by tablespace_name) b

where a.tablespace_name = b.tablespace_name and a.tablespace_name in ('UNDOTBS1','UNDOTBS2')

order by ((a.bytes - b.bytes) / a.bytes) desc;

开始分批次小量压测,将前一个步骤的数据量分批插入,保证能插入成功而且数据量一致。

begin

for i in 1..1000000 loop

insert into t_tx values(i,mod(i,10));

end loop;

commit;

end;

/

begin

for i in 1..1000000 loop

insert into t_tx values(i,mod(i,10));

end loop;

commit;

end;

/

再次查看回滚段大小,可以看到如下信息。

SQL> SQL> select a.tablespace_name,

round(a.bytes / 1024 / 1024 / 1024, 0) "sum G",

round((a.bytes - b.bytes) / 1024 / 1024 / 1024, 0) "used G",

round(b.bytes / 1024 / 1024 / 1024, 0) "free G",

round(((a.bytes - b.bytes) / a.bytes) * 2 3 4 5 100, 2) "used%"

from (select tablespace_name, sum(bytes) bytes

from dba_data_files

group by tablespace_name) a,

(select tablespace_name, sum(bytes) bytes, max(bytes) largest

from dba_free_space

group by tablespace_name) b

where a.tablespace_name = b.tablespace_name and a.tablespace_name in ('UNDOTBS1','UNDOTBS2')

order by ((a.bytes - b.bytes) / a.bytes) desc; 6 7 8 9 10 11 12 13

TABLESPACE_NAME sum G used G free G used%

--------------------- ---------- ---------- ---------- ----------

UNDOTBS1 0 0 0 99.95

SQL> select owner,round(sum(bytes)/1024/1024,2) as MB,status from DBA_UNDO_EXTENTS group by owner,status;

OWN MB STATUS

--- ---------- ---------

SYS .56 EXPIRED

SYS 118.38 UNEXPIRED

得到一个结论,只要在回滚段的峰值这个时间段,active的数值大小没超过undo表空间的大小,那就可以保证undo段的正常使用,不会让数据库异常。

5、总结

undo表空间的大小超过undo段使用的峰值,而且超过undo_retention时间内active和unexpected的数值大小,那这个undo表空间是完美的。

undo表空间超过了使用的undo峰值,那么它是可用的。

越写知识点越多,就到这吧,感觉都迷糊了。

相关内容

影视大全免费高清版旧版本
365地址

影视大全免费高清版旧版本

⌚ 08-25 👁️‍🗨️ 4806
Revit多久能学会?
365地址

Revit多久能学会?

⌚ 07-12 👁️‍🗨️ 6777

友情链接