2009年6月24日 星期三

如何解決Data Pump匯入中途因空間不足而暫停的問題

今天凌晨六點爬起來看Import的結果,結果我一個粗心大意,竟然沒發現Data File空間不足,導致工作Hang在那邊,一副事不關己的等我解決。錯誤的代碼分別ORA-39171為提示你說工作已經暫停(廢話,我用眼睛看不來嗎?),另一個是ORA-01653告訴你空間已經不足。解決的方式很簡單,只要另外再加一個Data File就可。

不過,有趣的是Data File本身的設定引起我的興趣。Data File本身的大小限制乃是受限於DB_BLOCK_SIZE(metalink:Doc ID: 468096.1),每個版本的Oracle各不同的設定:
以10.2版來說,DB_BLOCK_SIZE就是4096~8192 bytes間的值。而每個Data File的檔案大小以 Maximum Blocks x Maximum DB_BLOCK_SIZE計算。所以10.2版Data File的最大Size = (4194303 x 8192) /1024 /1024 /1024 = 32GB。因此在新增Data File的時候,就要注意到Data File的最大上限為何,否則就會收到 ORA-01144的錯誤(換句話說,並沒有所謂的檔案大小無上限,且其所在的作業系統也會有對檔案的物理限制)。

2009年6月16日 星期二

讓你的 SQL 指令斷行吧

常會為了輸出某些管理指令而使用spool 指令,但困擾的是如果需要同一個SQL內產出兩行不同指令 ,那麼分行就會是個問題。例如像是以下產出的指令就會連成一行:

SELECT 'TRUNCATE TABLE ' || table_name || ' drop usage; ' ||
'UPDATE myTableList SET status = ''F'' WHERE table_name = ''' || table_name || ''';'
FROM dba_tables
WHERE table_name like 'MGM%';

產出結果:

TRUNCATE TABLE MGM01 drop usage; UPDATE myTableList SET status = 'F' WHERE table_name = 'MGM01';

除了醜之外,command mode執行時還會因為兩個指令中間的分號出現 '字元錯誤'的錯誤提示。如果硬是拆分成兩個SQL指令分別產出 truncate table 跟 update 指令,想想就覺得很討厭。所以,最好的方式就是將兩個SQL指令字串斷行即可。

方法很簡單,加上 chr(13)就可了。改變如下:

SELECT 'TRUNCATE TABLE ' || table_name || ' drop usage; ' ||
chr(13)
'UPDATE myTableList SET status = ''F'' WHERE table_name = ''' || table_name || ''';'
FROM dba_tables
WHERE table_name like 'MGM%';

結案~

2009年6月8日 星期一

Update 多欄位時需注意Subquery資料需與目標Table一對一對映

Oracle更新多欄位的方式通常會以SET (column_name, column_name, ...) = (subquery4) 的形式執行更新。不過需要注意的是,必須確保目標Table的資料列能與Subquery一對一對的對應映。

例子中Multi-Column 的Update來看,如果將 t1 建立時的rownum改成 12 更新就會失敗;這時候就只好屈就於cursor來解了:

cursor
cur_t2 is
select table_name, tablespace_name
from t2;

for cur_rec in cur_t2 loop
update t1
set t1.tablespace_name = t2.tablespace_name
where t1.table_name = cur_rec.table_name;
end loop;

2009年6月2日 星期二

透過TNS_ADMIN部署TNSNAMES.ORA

前幾天遇到一個如何統一管理tnsnames.ora的問題,對於散落在user端的tnsnames.ora設定通常是一個小麻煩。基本上,只要透過logon script就可以輕鬆將統一的設定好的tnsnames.ora複製到user端,但手法卻醜陋了一點,更別提得要先登入系統時才會更新一次的問題。因此如果能讓user端讀取指定共享目錄下的tnsnames.ora,不是更輕鬆些?以後管理者只要維護該目錄下的tnsnames.ora,user端就能隨時讀取到最新的設定,皆大歡喜。

設定的方式相單簡單,主要準備幾個材料即可;
  1. 首先,準備好server端的分享目錄,假設為\\myServer\myShareFolder,將設定完整的tnsnames.ora放進去;
  2. 接下來找出user端的的oracle 的registry設定後,加入TNS_ADMIN。以9i為例,找到Oracle在C:\ORACLE\ora92\bin\oracle.key檔中記錄的Registry設定位址 Software\ORACLE\HOME0,接著打開 HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0,並加入字串「TNS_ADMIN」,設定其值為「\\myServer\myShareFolder」; 
  3. HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0的機碼匯出成ora9i_tnsnames.reg;
  4. 將上述準備好的reg檔以logon script的方式,以 regedit ora9i_tnsnames.reg /s 的方式部署到user端。
當下次user登入時便會在其oracle home registry中,匯入TNS_ADMIN的設定值,轉而讀取server上的設定而略過本機的tnsnames.ora設定。大功告成!logon script只要確定好部署完畢即可移除,但若有其他管理性目的則不在此述。以後管理者只要維護一份tnsnames.ora即可,user端也隨時可讀取到最新的設定,樂哉~