让你的应用程序不再对数据库的改动"感冒"(三)
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的冻结之后才行。也许那个命令只需要一小会儿时间,用户注销后也只需要等待一小会儿,但是设想一下如果这种改动要在一个业务高峰时候做的话,这种影响也许会变得非常糟糕。
(全文结束)