Oracle如何切换temp表空间以及需要注意的点
昨天有套库报/u01的磁盘90%使用率报警了,无法通过LVM在原盘基础上扩容,计划新增加磁盘并将能在线迁移的相关数据库文件迁移走。
其中,对于temp表空间的处理,我采取的方法实际和undo差不多,均是通过切换来达到目的。
版本是11.0.2.4.0.200714
记录一下遇到的一些问题。
假设现在的临时表空间为temp,我要切换成temp2。
参考mos文档How to Resize the Temporary Tablespace in a Production Environment (文档 ID 160681.1),切换的官方步骤很简单,如下:
1.create temporary tablespace temp2 tempfile '/data/temp02.dbf' size 10g autoextend off; <------这里文件总大小保持和原临时表空间一致,超过32G需要多个文件
2.alter database default temporary tablespace temp2;
3.alter database tempfile '/u01/app/oracle/oradata/xxxxdb/temp01.dbf' offline; <------官方的语句是"alter tablespace TEMP offline;",这个语法不支持临时表空间,也就是官方给的是错的;另外,有多少个文件就offline多少个
4.drop tablespace TEMP including contents and datafiles;
以上步骤需要注意的是,第2步骤原本我是通过修改当前默认临时表空间为temp的用户,将默认临时表空间修改为temp2。因为可能原来数据库中不止存在temp,甚至可能有临时表空间组。
--以下SQL会生成DCL语句,执行这些语句
select 'alter user '||username||' temporary tablespace temp2;' from dba_users where temporary_tablespace='TEMP';
但是这一步遇到了一个问题,我的库中存在用户"XS$NULL",会导致报错ORA-01031。(如果你的库没有这个用户,则可以用上边的语句这么做)。
17:32:46 SYS@test(201)> alter user XS$NULL temporary tablespace temp2;
alter user XS$NULL temporary tablespace temp2
*
ERROR at line 1:
ORA-01031: insufficient privileges
Elapsed: 00:00:00.00
官方明确指出无法对用户XS$NULL做任何alter user的语句。
如果想要更改默认临时表空间,只能通过上边第2步骤来更改库级别的默认临时表空间,也会同步更改XS$NULL 用户临时表空间。
只是,对于多个临时表空间的库来说(或者多个临时表空间组),会导致所有用户都使用了temp2,需要提前记录用户原来使用的临时表空间情况方便后续还原。
关于用户XS$NULL,这里简单介绍:
XSNULL 是在安装数据库组件 Oracle XML Database (XDB) 时创建的。它是一个内部帐户,表示会话中没有用户。轻量级会话基础结构(APEX 和 XDB 会使用它)会使用它,并且此用户的名称在使用轻量级会话的模块中是硬编码的。因此,XSNULL 必须存在于数据库中。请注意,由于 XSNULL 并不是真正的用户,因此只有 Oracle Database 实例才能访问此帐户。XSNULL 没有任何权限,没有人可以以 XSNULL 的身份进行身份验证,也不能将身份验证凭据分配给 XSNULL。
卸载 XDB 时会删除此帐户。
另外,上边第4步骤执行的时候可能卡住。
https://www.cnblogs.com/PiscesCanon/p/18279318
此时,查询该会话等待事件的信息,如下:
15:38:11 SYS@xxxxdb(597)> select event,status,state,blocking_session from v$session where sid=399;
EVENT STATUS STATE BLOCKING_SESSION
--------------------- ------- ---------- ----------------
enq: TS - contention ACTIVE WAITING 3
sid为399是执行第4步骤的会话,此时被sid=3的会话卡住,再次查询sid=3的会话信息:
15:38:35 SYS@xxxxdb(597)> select program,event,status,state,blocking_session from v$session where sid=3;
PROGRAM EVENT STATUS STATE BLOCKING_SESSION
--------------------- --------------------- ------- ---------- ----------------
oracle@xxxxdb (SMON) smon timer ACTIVE WAITING
根据SMON Blocking Drop Temporary Tablespace (文档 ID 1500044.1) 、DDL Operations (Alter and Drop) on Temporary Tablespace Hang (文档 ID 1911167.1),可能命中BUG。
BUG特征如下:防。
1.会话等待事件为:"enq: TS - contention",符合。
2.会话被SMON阻塞,符合。
3.阻塞会话的SMON等待事件为"SMON TIMER",符合。
4.数据库版本在11.2.0.3及以上,符合。
官方建议是打上补丁15913577,或者采取临时操作,这里贴上原始英文。
Complete all the needed prerequisites (create the new temp tablespace and set as default and no user is assigned to the old tablespace)
Bounce the DB
Once the DB starts up disconnect from SQLPLUS completely and close the console
Open a new console and launch SQLPLUS
Run the drop command as the VERY FIRST COMMAND
我试了下临时操作是不行的,后边看了下当前临时段的占用情况,发现旧的临时表空间temp依然被占用着。
16:16:15 SYS@xxxxdb(17)> SELECT s.username,sid,serial#,t.tablespace,contents,sql_address,extents,last_call_et
16:17:23 2 FROM v$session s,v$tempseg_usage t
16:17:23 3 WHERE s.saddr = t.session_addr;
USERNAME SID SERIAL# TABLESPACE CONTENTS SQL_ADDRESS EXTENTS LAST_CALL_ET
------------------------- ---------- ---------- --------------- --------------------------- ---------------- ---------- ------------
DBSNMP 8 7869 TEMP TEMPORARY 00 1 22
SYS 399 34247 TEMP2 TEMPORARY 00 1 1386
Elapsed: 00:00:00.00
DBSNMP用户是OEN客户端的会话,重启OEM客户端之后,第4步骤的会话立刻执行完成。
嘶,,,,,,感觉也不像BUG啊。
后续测试了下,新创建的数据库会话一旦执行删除临时表空间的语句时,会在当前临时表空间占用一点临时段空间。
如果是同一个会话操作同时切换两次表空间(比如temp->temp2,temp2->temp),需要注意这个问题。
PS:后边又找了个测试库打补丁,还是不行。只要解决占用问题即可。