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 privilegesElapsed: 00:00:00.00
官方明確指出無法對用戶XS$NULL做任何alter user的語句。
如果想要更改默認臨時表空間,只能通過上邊第2步驟來更改庫級別的默認臨時表空間,也會同步更改XS$NULL 用戶臨時表空間。
只是,對于多個臨時表空間的庫來說(或者多個臨時表空間組),會導致所有用戶都使用了temp2,需要提前記錄用戶原來使用的臨時表空間情況方便后續還原。
關于用戶XS$NULL,這里簡單介紹:
XS$NULL 是在安裝數據庫組件 Oracle XML Database (XDB) 時創建的。它是一個內部帳戶,表示會話中沒有用戶。輕量級會話基礎結構(APEX 和 XDB 會使用它)會使用它,并且此用戶的名稱在使用輕量級會話的模塊中是硬編碼的。因此,XS$NULL 必須存在于數據庫中。請注意,由于 XS$NULL 并不是真正的用戶,因此只有 Oracle Database 實例才能訪問此帳戶。XS$NULL 沒有任何權限,沒有人可以以 XS$NULL 的身份進行身份驗證,也不能將身份驗證憑據分配給 XS$NULL。
卸載 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 3sid為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 1386Elapsed: 00:00:00.00
DBSNMP用戶是OEN客戶端的會話,重啟OEM客戶端之后,第4步驟的會話立刻執行完成。
嘶,,,,,,感覺也不像BUG啊。
后續測試了下,新創建的數據庫會話一旦執行刪除臨時表空間的語句時,會在當前臨時表空間占用一點臨時段空間。
如果是同一個會話操作同時切換兩次表空間(比如temp->temp2,temp2->temp),需要注意這個問題。
PS:后邊又找了個測試庫打補丁,還是不行。只要解決占用問題即可。