undo 表空间使用案例分析(使用率100%,enq:US-contention,释放undo)

简介:  Undo参数SQL> show parameter undoNAME                                         TYPE                   VALUE------------------------...

 Undo参数
SQL> show parameter undo
NAME                                         TYPE                   VALUE
----------------------------------- ----------  --------------------
undo_management            string AUTO
undo_retention                     integer 900
undo_tablespace                 string UNDOTBS1

UNDO_MANAGEMENT:该初始化参数用于指定UNDO数据的管理方式。如果要使用自动管理模式,必须设置该参数为AUTO,如果使用手工管理模式,必须设置该参数为MANUAL,使用自动管理模式时,Oracle使用UNDO表空间管理undo管理,使用手工管理模式时,Oracle会使用回滚段管理undo数据,需要注意,使用自动管理模式时,如果没有配置初始化参数UNDO_TABLESPACE。Oracle会自动选择第一个可用的UNDO表空间存放UNDO数据,如果没有可用的UNDO表空间,Oracle会使用SYSTEM回滚段存放UNDO记录,并在ALTER文件中记载警告。

UNDO_TABLESPACE:该初始化参数用于指定例程所要使用的UNDO表空间,使用自动UNDO管理模式时,通过配置该参数可以指定例程所要使用UNDO表空间。在RAC(Real Application Cluster)结构中,因为一个UNDO表空间不能由多个例程同时使用,所有必须为每个例程配置一个独立的UNDO表空间。

UNDO_RETENTION:该初始化参数用于控制UNDO数据的最大保留时间,其默认值为900秒,从9i开始,通过配置该初始化参数,可以指定undo数据的保留时间,从而确定倒叙查询特征(Flashback Query)可以查看到的最早时间点

UNDO_POOL:这个参数是用来限定每个用户可以使用的撤销表空间的配额的,他的默认值是UNLIMITED ,但是你想想,如果一个事务发生了错误,占用了几乎全部的undo表空间,这个实例就这么一个表空间,你让别的会话的事务情何以堪啊,所以使用UNDO_POOL参数对每个事务进行限制。


相关视图

用户可以查看v$undostat视图可以监视撤销表空间的使用情况,他能显示与撤销表空间和相关事务有关的统计信息(如当前实例中撤销表空间的使用量),这样就可以通过配置v$undostat来提高效率。

V$UNDOSTAT 可以显示撤销空间运行的历史统计信息。用户可以查询撤销空间使用率(undo consumption rate),事务并发性(transaction concurrency),实例中最长的查询的运行时间等统计信息。通过这个视图,用户可以更好地估计在当前工作负荷下系统所需的撤销空间(undo space)容量。


用户可以使用V$transaction 和 V$rollstat视图监控事务和撤销空间的信息,对于自动撤销管理(automatic undo management)模式,V$ROLLSTAT视图能够展现自动撤销管理所使用的各个撤销段(undo segment)的情况。


Oracle 10g 数据库自动地调整用于控制撤销信息保存周期(undo retention period)的参数。撤销信息保存周期是指,撤销表空间中旧的撤销信息(即已提交事务的撤销信息)在被覆盖之前至少需要被保存的时间。数据库会收集撤销信息的使用情况,并根据统计结果及撤销表空间(undo tablespace)的大小对撤销信息保存周期进行调整。当数据库处于自动撤销管理(automatic undo management)模式下,其撤销信息保存周期的调整规则如下:

  • 对于存储参数为 AUTOEXTEND 的撤销表空间,如果空间情况允许,数据库将撤销信息保存周期设为比系统中最长的查询时间稍长。此外,如果空间情况允许,系统设定的撤销信息保存周期不会低于 UNDO_RETENTION 初始化参数。
  • 对于固定容量的撤销表空间,数据库将撤销信息保存周期设为撤销表空间所支持的最大值。这意味着数据库可以使用接近撤销表空间极限的容量为用户提供最长的撤销信息保存周期。The UNDO_RETENTION initialization parameter is ignored unless retention guarantee is enabled.
  • 撤销信息保存周期的自动调整不适用于 LOB 数据。LOB 列的撤销信息保存周期由UNDO_RETENTION 参数决定。
当一个固定容量的撤销表空间(undo tablespace)与一个自动扩展的撤销表空间(存储参数为 AUTOEXTEND)容量相同时,前者使用的撤销信息保存周期(undo retention period)调整方法通常能够提供更长的保存时间。这使回闪(flashback)操作可以追溯的更远,也使运行时间长的查询有更多的撤销数据(undo data )可用。



问题描述:

近几天发现Oracle10.2.0.4数据库undo tablespace表空间使用率很高(最高时达到100%),报警系统频繁报障undo tablespace表空间使用率过高。

TABLESPACE_NAME         TOTAL     USED        FREE       PUSED      PFREE
-----------------  ----------  ---------- ---------- ---------- ----------
UNDOTBS1             6141 % %

问题分析
2.1 业务系统影响
undo tablespace表空间使用率达到100%时,没有业务系统用户反映系统出现表空间不能扩展的报错(ORA-30036),但曾经出现过快照过旧报错(ORA-01555)
2.2 数据库日志
查看alert_instdb.log报警文件,发现从Tue May 18 10:51:27 2010到Sat May 22 14:55:59 2010,共出现了15次与undo tablespace有关的ORA-01555报错,这些报错都是由同一条SQL语句引起的(SQL ID: 1h54gg6shbrkh),语句执行时间都很长(在20万秒以上),最长执行时间达到355659 sec。
Tue May 18 10:51:27 2010
ORA-01555 caused by SQL statement below (SQL ID: 1h54gg6shbrkh, Query Duration=349634 sec, SCN: 0x0a1b.a93246fa):
Tue May 18 10:51:27 2010
select decode(temp_kp.mc,null,temp_hdhs.mc,temp_kp.mc) as mc,
decode(temp_kp.jzyje,null, 0,temp_kp.jzyje) as jzyje,
decode(temp_kp.jzyfs,null, 0,temp_kp.jzyfs) as jzyfs,
decode(temp_kp.bdcje,null, 0,temp_kp.bdcje) as bdcje,
decode(temp_kp.bdcfs,null, 0,temp_kp.bdcfs) as bdcfs,
decode(temp_kp.ptje,null, 0,temp_kp.ptje) as ptje,
decode(temp_kp.ptfs,null, 0,temp_kp.ptfs) as ptfs,
decode(temp_kp.dkje,null, 0,temp_kp.dkje) as dkje,
decode(temp_kp.dkfs,null, 0,temp_kp.dkfs) as dkfs,
decode(temp_kp.bgdlyje,null, 0,temp_kp.bgdlyje) as bgdlyje,
decode(temp_kp.bgdlyfs,null, 0,temp_kp.bgdlyfs) as bgdlyfs,
decode(temp_kp.gjhyyje,null, 0,temp_kp.gjhyyje) as gjhyyje,
decode(temp_kp.gjhyyfs,null, 0,temp_kp.gjhyyfs) as gjhyyfs,
decode(temp_kp.gjhyycpdlje,null, 0,temp_kp.gjhyycpdlje) as gjhyycpdlje,
decode(temp_kp.gjhyycpdlfs,null, 0,temp_kp.gjhyycpdlfs) as gjhyycpdlfs,
decode(temp_kp.gjhwysje,null, 0,temp_kp.gjhwysje) as

2.4 Undo tablespace空间使用情况
select file_name,autoextensible,bytes/1048576 MB,increment_by,maxbytes/1048576 Max_MB
from dba_data_files
where tablespace_name = 'UNDOTBS1';

FILE_NAME AUTOEXTENSIBLE MB INCREMENT_BY MAX_MB
/dev/rinstdbUNDO_lv NO 1023 0 0
/dev/rinstdbUNDO2_lv NO 3071 0 0
/dev/rinstdbUNDO3_lv NO 2047 0 0

select tablespace_name,status, sum(bytes)/1024/1024 MB, count(*) from dba_undo_extents
group by tablespace_name,status

TABLESPACE_NAME STATUS MB COUNT(*)
TS_UNDO EXPIRED 2.375 38
UNDOTBS1 UNEXPIRED 4344.75 2687
UNDOTBS1 EXPIRED 1796.0625 3146

UNDOTBS1表空间总空间是6141MB,已分配空间达到6140.8125MB,其中UNEXPIRED EXTENT空间占4344.75MB。

2.5 V$UNDOSTAT和DBA_HIST_UNDOSTAT
查询V$UNDOSTAT视图和DBA_HIST_UNDOSTAT数据字典可以看到:
1. 从2010-05-19 PM 10:53:38到2010-5-22 04:53:38 PM,MAXQUERYLEN值都保持在20万秒以上,MAXQUERYLEN最大值是285073s(2010-5-22 04:53:38 PM),
2. TUNED_UNDORETENTION保持在20万秒以上,TUNED_UNDORETENTION最大值是345742s (2010-5-26 09:13:38 AM),TUNED_UNDORETENTION当前值是255484(2010-5-27 02:43:38 PM)
3. SSOLDERRCNT累计值大于0
4. NOSPACEERRCNT一直都是0


从以上数据可以了解到,从2010-05-19 PM 10:53:38到2010-5-22 04:53:38 PM期间出现了多次异常超长时间查询,这些长时间查询导致TUNED_UNDORETENTION参数值变大,这些查询曾经导致ORA-01555报错,但没有导致DML语句出错。
注:从oracle10g开始,oracle提供了Automatic UNDO Retention特性,即oracle会根据实际情况自动调整undo_retention值,以尽可能避免ORA-01555的报错。v$undostat视图中几个主要列的解释:
MAXQUERYLEN Identifies the length of the longest query (in seconds) executed in the instance during the period. You can use this statistic to estimate the proper setting of the UNDO_RETENTION initialization parameter. The length of a query is measured from the cursor open time to the last fetch/execute time of the cursor. Only the length of those cursors that have been fetched/executed during the period are reflected in the view.
SSOLDERRCNT Identifies the number of times the error ORA-01555 occurred.
NOSPACEERRCNT Identifies the number of times space was requested in the undo tablespace and there was no free space available. That is, all of the space in the undo tablespace was in use by active transactions. The corrective action is to add more space to the undo tablespace.
TUNED_UNDORETENTIONSystem tuned value indicating the period for which undo is being retained

总结及建议
3.1 Undo tablespace使用率100%原因
从oracle10g开始,oracle提供了Automatic UNDO Retention特性,即oracle会根据实际情况自动调整undo_retention值,从2010.5.18至2010.5.22期间产生了多次超长时间查询,这段期间MAXQUERYLEN值保持在20万秒以上,为了尽可能避免ORA-01555的报错,尽可能保留更多的UNEXPIRED EXTENT,ORACLE会首先选择在undo tablespace中扩充rollback segment,所以undo tablespace使用率会不断上升,最终导致了undo tablespace空间使用率达到100%。
3.2 Undo tablespace空间监控方法
undo tablespace空间使用率达到100%,只是意味着所有的空间都已经分配给rollback segment,但并不一定会影响到业务的select和insert、delete、update操作,因为rollback segment中的空间是可以重用的。在oracle10g,不能通过监控dba_free_space数据库字典的方法去获得undo tablespace的使用情况,可以考虑通过以下方法进行监控:
1. 监控v$undostat视图,主要包括MAXQUERYLEN、SSOLDERRCNT、NOSPACEERRCNT列值,如:MAXQUERYLEN大于36000秒则报警、SSOLDERRCNT大于0次(或一定次数)则报警、NOSPACEERRCNT大于0次则严重警告等;
2. 监控平均每一秒钟所需的最少回滚表空间容量,如果超过一定范围则报警
SELECT (UR * (UPS * DBS)) + (DBS * 24) AS "Bytes"
FROM (SELECT value AS UR FROM v$parameter WHERE name = 'undo_retention'),
(SELECT (SUM(undoblks)/SUM(((end_time - begin_time)*86400))) AS UPS FROM v$undostat),
(select block_size as DBS from dba_tablespaces where tablespace_name=
(select value from v$parameter where name = 'undo_tablespace'));

     Bytes
----------
 413215736

那么一个undo表空间的理论大小为:413215736*900

对于oracle10g版本,使用如下命令强制undo保存时间

alter tablespace undotbs1 retention guarantee;


实例二:

这几天遇到一个错误,我也不知道算不算错误吧,因为没有报错,只是在那突然的短短2分钟内表的操作突然降低了,导致了该软件重新启动。查看alert日志没有报错,而是在ASH里找到了TOP SQL框有一个这样的错误,使我百思不得其解。查看该SQL语句只是简单的一个更新,并不需要优化。最后再百度、google的帮助下终于找到了错误原因,原来与UNDO的设置有关。首先来介绍下undo_retention参数,该参数是撤销段的最短保留时间,而在默认情况下Oracle将根据表空间的大小和历史使用情况,自动调整undo信息保存时间,同时忽略 undo_retention的值,除非undo_retention的guarantee 特性被启用.也就是执行以下命令:

ALTER TABLESPACE UNDOTBS RETENTION GUARANTEE;

在自动调整启用的情况下,实际的撤销信息最短保留时间可以通过查询V$UNDOSTAT视图上的TUNED_UNDORETENTION列获得。往往最短保存时间远远大于设定的UNDO_RETENTION。UNDO自动优化功能能够最大限度的使用undo表空间,满足大部分的sql执行,但是也带来一个问题:很多事务执行完毕之后,发现UNDO表空间会在很长时间都一直保持着使用率是接近100%的状态,active 状态的很少。这种接近状态还无法手工的收缩,甚至于重启数据库实例也无法缓解,而此时常常会收到undo表空间的监控报警。

再来说说enq: US - contention问题
这是oracle10g中开始出现的bug(在11.1.0.7中仍有这个BUG),当因为系统activity增加或者降低的时候,oracle SMON进程会自动ONLINE或者OFFLINE rollback segments。这样导致某些与undo segments相关的latch或者enqueue被hold住太长时间,导致系统很多活跃session都开始等待enq: US - contention。可以同时使用以下解决方法:

1. 设置event让SMON不自动OFFLINE回滚段。

alter system set events '10511 trace name context forever, level 1';

2. 设置参数_rollback_segment_count :表示有多少rollback segment要处于online的状态;可以将该数值设置为数据库最繁忙的时候的回滚段数目。

alter system set "_rollback_segment_count"=;
这里以‘_’开头的为隐藏参数,通过show parameter 是看不到的,可以通过以下语句:

select a.ksppinm name, b.ksppstvl value, a.ksppdesc description
from x$ksppi a, x$ksppcv b
where a.indx = b.indx
and a.ksppinm like '%_rollback_segment_count%';


3.  undo autotune bug多多。最好disable。
alter system set "_undo_autotune"= false;
这种方法就是关闭了UNDO的自动调整功能,同事也能解决掉UNDO表空间会在很长时间都一直保持着使用率是接近100%的问题。

4.  有一个patch: A fix to bug 7291739 is to set a new hidden parameter, _highthreshold_undoretention to set a high threshold for undo retention completely distinct from maxquerylen.

alter system set "_highthreshold_undoretention"=;


案例三:

一.概述:

使用IMPDP工具导入大表(166G)数据时,报undo表空间不能扩展,导入工作失败.手工停止了impdp后,undo表空间存在无法自动释放的故障.本文主要描述如何通过重建undo表空间来手工释放undo表空间.

数据库环境的描述:

OS: AIX 6.1+HACMP 5.3

DB: ORACLE 10.2.0.5 RAC

二.问题的描述

impdp 导入数据时,报ora-30036错误

$impdp user/passwd directory=imp_dir dumpfile=big_table_%U.dmp parallel=10 logfile=imp_big_table.log

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


检查数据库的归档日志文件,也发现了这个报警

more /oracle/admin/*/bdump/alert_{SID}.log|grep undo

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

强行终止了impdp的操作,impdp的进程在操作中已不见

# ps -ef|grep impdp
root 8650752 8061396 0 15:02:08 pts/1 0:00 grep impdp

卸载数据文件所在的文件系统时,发现无法下载

SQL> select * from dba_directories

OWNER DIRECTORY_NAME DIRECTORY_PATH
------ -------------- ----------------

SYS imp_dir /imp_data

#umount /imp_data

umount: 0506-349 Cannot unmount /dev/imp_data: The requested resource is busy.

检查UNDO 表空间的使用情况,如下,存在一个两个比较大的EXPIRED的undo segment.

SQL> select owner,segment_name,sum(bytes/1024/1024) from dba_undo_extents group by owner,segment_name order by 3
OWN SEGMENT_NAME SUM(BYTES/1024/1024)
--- ------------------------------ --------------------
.........

SYS _SYSSMU12$ 26.125
SYS _SYSSMU9$ 27.125
SYS _SYSSMU7$ 45.125
SYS _SYSSMU18$ 72.125
SYS _SYSSMU20$ 72.125
SYS _SYSSMU10$ 72.125
SYS _SYSSMU1$ 83.125
SYS _SYSSMU6$ 3563.1875
SYS _SYSSMU8$ 9524.4375

SQL>select tablespace_name,status,sum(bytes/1024/1024) from dba_undo_extents group by tablespace_name,status;
TABLESPACE_NAME STATUS SUM(BYTES/1024/1024)
--------------- --------- --------------------
UNDOTBS1 ACTIVE 47.0625
UNDOTBS2 EXPIRED 291.25
UNDOTBS1 UNEXPIRED 285.875
UNDOTBS1 EXPIRED 13063.6875

在metalink上,查找相关信息,看到有一个bug,说的是:undo表空间不足的时候,不会overwrite expired的undo segment。这个bug是10.2.0.3,9.2.0.8版本上发生,当前数据库的版本为10.2.0.5,不应该是这个bug引起的。

三.问题的分析

数据库的环境是10.2.0.5 RAC,UNDO表空间不足发生在node1的undotbs1上,为了不影响数据库的运行,首先为该表空间增加了空间。

SQL> alter tablespace undotbs1 add datafile '/dev/rora_data_03' size 11518m;

尝试通过重新启动数据库,来释放undo表空间上的内容,结果失败,undotbs1仍然存在大量的expried的segment不能释放(这个数据库的undo 是自动管理的)

因为umount 导入文件系统也失败,考虑是不是因为手工强行停止了impdp的操作,导致了操作系统中还有相关进程没有完全停掉。所以采用了重新启动数据库服务器的方式来释放相关的文件系统的锁。

四.问题的解决

重新启动数据库服务器后,尝试umount 文件系统(/imp_data),结果成功.

现在剩下的问题是,如何shrink undo segment的问题,总不能让那么多的undo表空间就象太空垃圾一样,存在在数据库中.

在metalink上找到相关的文档:How to Shrink the datafile of Undo Tablespace [ID 268870.1]

按照文档介绍的方法,进行了下面的操作

SQL>create undo tablespace undotbs3 datafile '/dev/rora_data_02' size 11518m extent management local;

SQL>alter system set undo_tablespace='UNDOTBS3' scope=both sid='JLZDH1';

SQL>drop tablespace undotbs1 including contents;

ORA-30013 : undo tablespace undotbs1 is currently in use

在删除undo表空间undotbs1时,报表空间在使用,无法删除的错误.

重新启动数据库,再次查看undo表空间的情况

SQL> show parameter undo

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 450
undo_tablespace string  UNDOTBS3
SQL> select tablespace_name,status,sum(bytes/1024/1024) from dba_undo_extents group by tablespace_name,status;

TABLESPACE_NAME STATUS SUM(BYTES/1024/1024)
------------------------------ --------- --------------------
UNDOTBS3 UNEXPIRED 6.25
UNDOTBS2 EXPIRED 291.25
UNDOTBS1 EXPIRED 7152.1875
UNDOTBS3 EXPIRED 13.0625

再次尝试删除undotbs1,成功了.

SQL> drop tablespace undotbs1 including contents;

Tablespace dropped.

SQL> select tablespace_name,status,sum(bytes/1024/1024) from dba_undo_extents group by tablespace_name,status;

TABLESPACE_NAME STATUS SUM(BYTES/1024/1024)
------------------------------ --------- --------------------
UNDOTBS3 UNEXPIRED 2.3125
UNDOTBS2 EXPIRED 291.25
UNDOTBS3 EXPIRED 17

五.总结

impdp/expdp是oracle提供的数据库数据导入/导出的工具,速度比旧工具imp/exp要快很多,但也存在很多的bug,由于加入了job方式的管理,异常出现的机会比较多.曾经遇到过,手工终止impdp操作,导致了system表空间被大量占用的问题.本次又遇到undo表空间不能释放的问题.虽然数据泵有很多问题,但使用了parallel并行处理后,速度提升不是一般的多,所以日常工作中,还是首选数据泵工具.

undo表空间不能释放时,最好的解决办法就是:

1.重新建立一个新的undo表空间.

2.设置数据库的undo表空间为新的undo表空间

3.删除旧的undo表空间及其内容


相关文章
|
SQL 监控 Oracle
Oracle 数据库发生等待事件:enq: TX - row lock contention ,排查思路
Oracle 数据库发生等待事件:enq: TX - row lock contention ,排查思路
Oracle 数据库发生等待事件:enq: TX - row lock contention ,排查思路
|
11月前
|
关系型数据库 MySQL 数据库
修改innodb_buffer_pool_instances解决mysqlbinlog恢复慢的问题
一个客户的mysql数据库恢复在最后一步是滚binlog,结果恢复特别慢,CPU占用率100%,磁盘IO几乎是零,show processlist发现线程在sleep。从general log里面看不到任何动静,似乎找不到解决的办法。
334 0
|
关系型数据库 MySQL SQL
Innodb undo之 undo结构简析
水平有限,如果有误请指出 参考: 阿里内核月报 姜老师的MySQL内核:innodb存储引擎 做一个简单的记录,自己备用 一、大体结构 rollback segments(128) undo segments(1024) undo log (header insert/modify .
1534 0
|
关系型数据库 SQL
Innodb undo之 undo物理结构的初始化
水平有限,如果有误请指出。 一直以来未对Innodb 的undo进行好好的学习,最近刚好有点时间准备学习一下,通过阿里内核月报和自己看代码的综合总结一下。本文环境: 代码版本 percona 5.7.22 参数 innodb_undo_tablespaces = 4 及使用了4个undo tablespace 参数 innodb_rollback_segments = 128 本文描述使用如上参数的设置。
2416 0
|
关系型数据库 测试技术 自然语言处理