一次Undo表空间耗尽问题

Undo表空间耗尽问题

1、 问题描述

oracle版本19.16,发现undo表空间使用率过高,查询发现事物占用的表空间与undo表空间 active 状态的空间大小不一致

事物 使用 undo 表空间 sql 查询:

SELECT s.username,

       s.sid,

       pr.PID,

       s.OSUSER,

       s.MACHINE,

       s.PROGRAM,

       rs.segment_id,

       r.usn,

       rs.segment_name,      

       r.rssize/1024/1024,

       sq.sql_text

  FROM gv$transaction t, gv$session s, gv$rollstat r, dba_rollback_segs rs ,gv$sqltext  sq,gv$process pr

WHERE s.saddr = t.ses_addr

   AND t.xidusn = r.usn

   AND rs.segment_id = t.xidusn

   AND s.sql_address=sq.address

   AND s.sql_hash_value = sq.hash_value

   AND s.PADDR=pr.ADDR

ORDER BY t.used_ublk DESC ,sq.PIECE;

 

  undo表空间 active 的过大 与事物占用空间相差太大

SELECT tablespace_name,status,SUM (bytes)/1024/1024 "Bytes(M)" FROM dba_undo_extents GROUP BY tablespace_name,status;

 

 

2、 问题分析

排查过程中间 预估 dba/v$ 视图与基表的收集问题,尝试根据基表来查结果,未果。

后面 mos上查到一片文档:

High UNDO Tablespace Usage Caused By Recursive SQL f3yfg50ga0r8n From KTSJ Slave Process (Doc ID 3013880.1)

 

查询消耗的 sql_id确实是:“ f3yfg50ga0r8n

select MAXQUERYID,count(*) from gv$undostat group by MAXQUERYID;

通过 gv$session 查询确实有 KTSJ Slave执行,事件“Space Manager: slave idle wait”,也就是回收undo空间一直处于等待状态

select SID,SERIAL#,SCHEMANAME,TYPE,SQL_ID,SQL_CHILD_NUMBER,SQL_EXEC_START,MODULE,ACTION,ACTION_HASH,EVENT from gv$session where SQL_ID='f3yfg50ga0r8n';

查询 sql_id对应的sql:

select SQL_TEXT,SQL_ID,EXECUTIONS,LOADS,PARSE_CALLS,INVALIDATIONS from v$sql where SQL_ID='f3yfg50ga0r8n';

Sql为:select obj# from obj$ where dataobj# = :1

3、问题原因  

这是一个 bug,Bug 3633060,“ KTSJ slave ”执行空间管理协调( SMCO 出现了资源等待 但是目前 oracle开发团队未发布补丁

 

4、 问题解决

Bug 36330602得到修复之前,请考虑应用以下解决方案。

高了就关 smco:

ALTER SYSTEM SET "_enable_space_preallocation" = 0;

低了就开 smco,3也是默认参数:

ALTER SYSTEM SET "_ENABLE_SPACE_PREALLOCATION" = 3;

 

5、 技术原理 smco

smco的含义

SMCO (Space Management Coordinator) For Autoextend On Datafiles And How To Disable/Enable (Doc ID 743773.1)

 

 

翻译:

 

 

6、 总结建议 

1、该问题 最终结论( Bug 36330602,未发布的bug)(Doc ID 3013880.1)

2、我们要了解undo表空间,Undo段中区3中状态: DBA_UNDO_EXTENTS的STATUS列 三种状态:

ACTIVE 未提交的 Undo信息 事物还在活动, ACTIVE状态的Undo区不会被覆盖。

EXPIRED 过期的 Undo信息 事务已经提交且超过了 UNDO_RETENTION指定时间,该状态可以被覆盖使用。

  UNEXPIRED 提交的未过期 Undo信息:表示事务已经提交但是还没有超过UNDO_RETENTION指定时间,该状态可以被覆盖使用。

3、Undo相关报错

ORA-30036

如果 undo 表空间设置为 guarantee, 那么当 undo表空间的 expire d段不够时 , 不会覆盖 unexpire d状态的undo段 , 就会出现事务失败 ,ORA-30036 错误。

ORA-01555

如果 undo 表空间设置为 noguarantee, 那么当 undo表空间的 expire d不够时 , 会强行覆盖 unexpired 的段 , 来保证事务的成功执行 , 这样可能会导致出现 ORA-01555 错误 , 因为保留的旧数据被覆盖掉了。

查看是否为 guarantee

select tablespace_name,contents,retention from dba_tablespaces;

 

Undo_retention 默认 900,就是15分钟 只要表空间足够, Oracle内部会尽量保证将Undo数据保留超过undo_retention设置的时间。

4、 事务回滚

事物未回滚情况:数据库 Abort,再启动;Kill;未提交,rollback;

回滚过程:

SMON 进程的 CPU 使用率高

在大型事务恢复期间数据库可能会挂起。

如果数据库被关闭中止,则数据库可能在随后的启动过程中挂起。

并行事务恢复

FAST_START_PARALLEL_ROLLBACK

LOW- 将最大并行度限制为 2 * CPU_COUNT   默认值

HIGH- 将最大并行度限制为 4 * CPU_COUNT

串行事务恢复

此模式顺序恢复事务。

FAST_START_PARALLEL_ROLLBACK 参数设置为 false 将启用串行事务恢复。

alter system set fast_start_parallel_rollback=false;

死事务,一般是事务正在跑的时候,被 kill掉了,或者数据库shutdown abort了,那么当数据库再次启动的时候,这些事务就需要做回滚。

在一般情况下,并发的回滚总是比串行的快,一般在系统资源可以接受的范围内采用并发回滚,但是 也有 例外 情况 ,就是并发的子进程之间存在资源冲突的情况 所以我们有时候发现回滚时业务也卡住了

在并发子进程之间需要的资源冲突时,往往此时 smon的等待事件是长期处于Wait for stopper event to be increased,而子进程的等待事件是较多出现Wait for a undo record。此时,就是子进程冲突了。并发的回滚速度反而不如串行的回滚速度。冲突时,我们需要把fast_start_parallel_rollback 改成 false。

 

死事务 回滚段查询

select b.name     useg,

       b.inst#    instid,

       b.status$  status,

       a.ktuxeusn xid_usn,

       a.ktuxeslt xid_slot,

       a.ktuxesqn xid_seq,

       a.ktuxesiz undoblocks,

       a.ktuxesta txstatus

  from x$ktuxe a, undo$ b

 where a.ktuxecfl like '%DEAD%'

   and a.ktuxeusn = b.us#;

 

 

确认事务完成恢复的时间

select usn,

       state,

       undoblockstotal "Total",

       undoblocksdone "Done",

       undoblockstotal - undoblocksdone "ToDo",

       decode(cputime,

              0,

              'unknown',

              sysdate + (((undoblockstotal - undoblocksdone) /

              (undoblocksdone / cputime)) / 86400)) "Estimated time to complete"

  from v$fast_start_transactions;

 

 

 USN STATE     Total       Done       ToDo    Estimated time to c

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

11005 RECOVERING            17772       6624      11148 202 4 -0 7 -03 14:46:05

查询并行恢复的数量:

select * from v$fast_start_servers;

 

STATE       UNDOBLOCKSDONE        PID XID

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

RECOVERING            6624         27 FD2A0B008A000000

RECOVERING               0         30 FD2A0B008A000000

RECOVERING               0         32 FD2A0B008A000000

RECOVERING               0         33 FD2A0B008A000000

 

查询事务恢复的对象:

select decode(px.qcinst_id,

              NULL,

              username,

              ' - ' || lower(substr(s.program, length(s.program) - 4, 4))) "Username",

       decode(px.qcinst_id, NULL, 'QC', '(Slave)') "QC/Slave",

       to_char(px.server_set) "Slave Set",

       to_char(s.sid) "SID",

        s.serial#,

       decode(px.qcinst_id, NULL, to_char(s.sid), px.qcsid) "QC SID",

       px.req_degree "Requested DOP",

       px.degree "Actual DOP"

  from gv$px_session px, gv$session s

 where px.sid = s.sid(+)

   and px.serial# = s.serial#

 order by 5, 1 desc;

 

select distinct current_obj#

  from v$active_session_history

 where SESSION_ID = 145

   and SESSION_SERIAL# = 15;  

 select Object_name, object_type from dba_objects where object_id = 77211;

 

select * from v$fast_start_transactions;

USN        SLT        SEQ STATE            UNDOBLOCKSDONE UNDOBLOCKSTOTAL        PID    CPUTIME  PARENTUSN  PARENTSLT  PARENTSEQ XID              PXID             RCVSERVERS

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

11005         11        138 RECOVERING                 5555           17772         27         21          0          0          0 FD2A0B008A000000 0000000000000000          3

 

select * from v$rollname where usn=11005;

       USN NAME

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

     11005 _SYSSMU11005_3138824131$

 

alter system dump undo block "_SYSSMU11005_3138824131$" XID 11005 11 138;

 

select * from v$diag_info where name='Default Trace File';

 

object number objn )或者 object id objd

 

more /ora11203/app/diag/rdbms/crmdb/crmdb/trace/crmdb_ora_8070.trc |grep objn |more

* Rec #0x2e  slt: 0x0b  objn: 76496(0x00012ad0)  objd: 76496  tblspc: 4(0x00000004)

* Rec #0x2d  slt: 0x0b  objn: 76495(0x00012acf)  objd: 76495  tblspc: 4(0x00000004)

* Rec #0x2c  slt: 0x0b  objn: 83147(0x000144cb)  objd: 83147  tblspc: 4(0x00000004)

* Rec #0x2b  slt: 0x0b  objn: 76497(0x00012ad1)  objd: 76497  tblspc: 4(0x00000004)

 

select owner,object_name,object_type from dba_objects where object_id in ('76496','76495','83147','76497'); 

 


请使用浏览器的分享功能分享到微信等