讓你的應用程序不再對數據庫的改動"感冒"(三)
2024-07-21 02:08:36
供稿:網友
原著作者:jim czuprynski
lbl(looking before leaping)三思而后行
前面所述的技術只有在開發前計劃一組新的數據庫對象或者修正原有的數據庫對象時,能夠取得很好的效果。但是我總是會發現,當我們在進行這種開發規劃的時候,運行中的應用程序往往不可避免地受到中斷。換句話說,一個好的計劃應該保護現有的應用免受中由于數據庫對象改變引起的重編譯或者無效導致的中斷之苦。
明白在使對象有效前會發生什么重大影響
在我開始講述改變數據庫對象之前,要重點強調一點,請務必要仔細檢查每一個待改變的數據庫對象防止導致無效錯誤。在過去的幾年內,在焦急的開發員和撓人的主管的催促下,我曾經有意或無意地違反了這些建議,通常會導致應用程序執行性能的下降。
下面的代碼可以幫助你檢查通過重編譯哪些對象將會無效。
sql> set wrap off
sql> ttitle center "parent and dependent objects"
sql> break on par_typ skip 1 on par_sts skip 1 on par_obj skip 1 noduplicates
sql> column par_typ format a12 heading "type"
sql> column par_sts format a08 heading "status"
sql> column par_obj format a16 heading "parent"
sql> column dep_obj format a16 heading "child"
sql> column dep_typ format a12 heading "type"
sql> column dep_sts format a08 heading "status"
sql> select
2 o1.object_type par_typ,
3 o1.status par_sts,
4 o1.object_name par_obj,
5 o2.object_name dep_obj,
6 o2.object_type dep_typ,
7 o2.status dep_sts
8 from
9 public_dependency pd,
10 all_objects o1,
11 all_objects o2
12 where pd.referenced_object_id = o1.object_id
13 and pd.object_id = o2.object_id
14 and o1.object_name = 'employees'
15 order by par_obj;
parent and dependent objects
type status parent child type status
------------ -------- ---------------- ---------------- ------------ --------
table valid employees pkg_security package body invalid
bv_employees view valid
emp_details_view view valid
pkg_security package body valid
secure_employees trigger valid
update_job_histo trigger valid
6 rows selected.
在重編譯以后,一定要檢查哪些無效的對象。然后還是再檢查
很多次,我曾經目睹了這樣的情形:utlrp.sql重編譯器或者第三方的軟件沒有重編譯所有最近無效的對象。至少,這會導致一些問題;在最壞的情況下,除非有人注意到了這一點,應用程序將完全不能存取數據庫。
舉個例子,不久前我花費了整整90分鐘外加一個下午幫助一個程序員調試powerbuilder程序訪問oracle開發數據庫時遇到的ora-00942錯誤"table not found",但是相同的代碼卻可以在生產數據庫上正確運行。當我們在調試程序的時候,這個錯誤看上去是間歇出現和重現的。
我想起以前遇到過這種情況并且花費了很多時間來折磨我的大腦,最終具有諷刺意味的是罪魁禍首是無效的數據庫對象。最終發現是因為另外一個程序員刪除并且重建了原來的一個表,但是有一大堆其他的數據庫對象引用了這個表,而他卻沒有重新編譯這些對象,導致它們都無效了。
密切提防global temporary tables
最后一個告誡:如果你使用全局臨時表(gtts)來存儲和計算狀態信息,小心程序改變它會帶來的后果。我曾經把進行了一個最平常不過的改動,把gtt的varchar(15)字段改變成varchar(25)。然而這個特殊的gtt通過指定了on commit preserve rows選項,從而可以被一個程序包用來存儲每個連接用戶的信息。oracle頑固地拒絕了alter table命令除非我要求所有應用程序的用戶都注銷,解除了對gtt的凍結之后才行。也許那個命令只需要一小會兒時間,用戶注銷后也只需要等待一小會兒,但是設想一下如果這種改動要在一個業務高峰時候做的話,這種影響也許會變得非常糟糕。
(全文結束)