在某次用户现场遇到一则临时表空间相关的案例,简要收录于此,供读者朋友们参考。
在数据库启动过程中,遇到ORA-00600错误,数据库无法Open打开。数据库告警日志文件记录如下信息。
首先Mount加载数据库:
Sun Apr 13 07:21:23 2008 ALTER DATABASE MOUNT Sun Apr 13 07:21:31 2008 Successful mount of redo thread 1, with mount id 3250187131. Sun Apr 13 07:21:31 2008 Database mounted in Exclusive Mode. Completed: ALTER DATABASE MOUNT
接下来在Open阶段,数据库要执行前滚(Rolling Forward)操作:
Sun Apr 13 07:21:31 2008 ALTER DATABASE OPEN Beginning crash recovery of 1 threads Sun Apr 13 07:21:32 2008 Thread recovery: start rolling forward thread 1 Recovery of Online Redo Log: Thread 1 Group 1 Seq 2079555 Reading mem 0 Mem# 0 errs 0: /ha_soft/oracle/data/oradata/tvdb/redo03.log Mem# 1 errs 0: /ha_soft/oracle/data/oradata/tvdb/redo011.log Sun Apr 13 07:21:32 2008 Thread recovery: finish rolling forward thread 1 Thread recovery: 9 data blocks read, 9 data blocks written, 259 redo blocks read Crash recovery completed successfully
注意到这里前滚操作成功完成,实例完成了Crash recovery,接下来增进日志,打开Redo Thread:
Sun Apr 13 07:21:32 2008 Thread 1 advanced to log sequence 2079556 Thread 1 opened at log sequence 2079556 Current log# 8 seq# 2079556 mem# 0: /ha_soft/oracle/data/oradata/tvdb/redo08.log Current log# 8 seq# 2079556 mem# 1: /ha_soft/oracle/data/oradata/tvdb/redo081.log Successful open of redo thread 1.
接下来SMON执行Cache Recovery,OPEN打开数据库:
Sun Apr 13 07:21:32 2008 SMON: enabling cache recovery SMON: enabling tx recovery Sun Apr 13 07:21:35 2008 Completed: ALTER DATABASE OPEN
数据库OPEN完成之后,SMON马上发现错误,抛出600异常,数据库崩溃:
Sun Apr 13 07:21:38 2008 Errors in file /ha_soft/oracle/admin/tvdb/bdump/tvdb_smon_10030.trc: ORA-00600: internal error code, arguments: [ktfdfinsert1], [34], [30902], [], [], [], [], [] Sun Apr 13 07:21:39 2008 Errors in file /ha_soft/oracle/admin/tvdb/bdump/tvdb_smon_10030.trc: ORA-00600: internal error code, arguments: [ktfdfinsert1], [34], [30902], [], [], [], [], [] Sun Apr 13 07:21:39 2008 SMON: terminating instance due to error 600 Instance terminated by SMON, pid = 10030
根据数据库启动信息判断,数据库能够顺利完成回滚和前滚过程,也就说明REDO和UNDO不存在问题,而在Open之后,Oracle需要通过SMON进程进行一些临时段的清理,数据库恰好在这一阶段出现问题,根据错误提示显示,出现问题的位置是 34 号文件,数据块30902 ,34号文件,根据数据库的参数文件、历史信息判断,正是一个临时文件。在Oracle8i中,这个问题被标记为 Bug。
此时我们可以临时禁止SMON进程进行临时段清理工作,这里用到Oracle的10061事件,在启动参数文件中设置:
event="10061 trace name context forever, level 10"
然后数据库可以Open打开,启动之后确认问题数据文件:
QL> select file#,name,status from v$datafile where file#=34; FILE# NAME STATUS -------------------------------------------------------------------------------- 34 /ha_soft/oracle/data/oradata/tvdb/TVDB_TMP1.dbf ONLINE SQL> select ts#,file# from v$datafile where name like '%TVDB_TMP%'; TS# FILE# ---------- ---------- 23 34
通过查询我们可以找到存在问题的区间(Extents):
SQL> select u1.file#, u1.block#, u1.length, f2.block# from uet$ u1, fet$ f2 2 where u1.file# = f2.file# and 3 u1.block# <= f2.block# and f2.block# < u1.block#+u1.length 4 and u1.ts# = f2.ts#; FILE# BLOCK# LENGTH BLOCK# ---------- ---------- ---------- ---------- 34 69782 20 69782 34 30902 20 30902
确认这是临时数据段:
SQL> select * from uet$ where FILE#=34; SEGFILE# SEGBLOCK# EXT# TS# FILE# BLOCK# LENGTH ---------- ---------- ---------- ---------- ---------- ---------- ---------- 86 158782 2 23 34 69782 20 86 158782 9 23 34 30902 20 86 158782 13 23 34 2 20 86 158782 14 23 34 22 20 86 158782 15 23 34 42 20
由于临时段存放的是临时数据,备份数据后我们可以清理这两个临时区间,重启数据库之后,数据库恢复正常。
SQL> delete from uet$ where ts#=23 and file#=34 and BLOCK#=69782; 1 row deleted. SQL> delete from uet$ where ts#=23 and file#=34 and BLOCK#=30902; 1 row deleted. SQL> commit; Commit complete. SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> startup ORACLE instance started. Total System Global Area 5211926204 bytes Fixed Size 102076 bytes Variable Size 680108032 bytes Database Buffers 4529651712 bytes Redo Buffers 2064384 bytes Database mounted. Database opened. SQL> select * from uet$ where FILE#=34; no rows selected
这是一个基于字典管理表空间的临时文件存在的问题,其根本原因在于,一个存在于UET$中被使用的Extent,当需要释放这个Extent时,发现该Extent在FET$存在,也就是说其存在性出现歧义,同时存在USED和FREE两种状态,这是数据库的一致性出现了问题,由于是临时段,我们可以手工对其进行处理,解决这个问题。
在这个问题中,我们应当学习到的知识是,在数据库OPEN之后,SMON进程将会负责临时段的清理和回收工作,这一工作在任何版本中都是非常重要的。