我会选择选项 #1 - 使用数据库链接的集中式功能。
数据库链接名声不好。主要原因之一是太多人使用公共数据库链接,任何连接到数据库的人都可以使用该链接。这显然是一场安全噩梦,但这不是默认设置,而且很容易避免这个陷阱。
数据库链接的其他一些问题:
- 对于数百万行的大量插入,它们表现不佳。另一方面,他们擅长许多小的 SELECT 或 INSERT。我经常在 10 年前的硬件上同时打开数百个链接并获取数据,而且效果很好。
- 它们使执行计划更难排除故障。
- 并非所有数据类型都受原生支持。这在 12.2 中更好,但在早期版本中,您需要使用 INSERT 将 CLOB 等数据类型移动到表中,然后从这些表中读取。
- 对于 DDL,您需要使用
DBMS_UTILITY.EXEC_DDL_STATEMENT@LINK_NAME('create ...');
确保仅在其中使用 DDL。其他类型的命令将静默失败。
- 在极少数情况下,链接可能会无限期挂起,例如数据库有存档错误或保证还原点已满。(这真是因祸得福 - 许多工具(如 Oracle Enterprise Manager)都无法捕捉到这些问题。您可能希望有一个后台作业检查运行时间超过 X 分钟的数据库链接查询。)
链接不应该是硬编码的,否则它们可能会使包无效。但这可能无关紧要——您可能希望遍历数据库列表并使用动态 SQL。如果链接不存在,则很容易创建一个新链接。这是一个例子:
declare
v_result varchar2(4000);
begin
--Loop through a configuration table of links.
for links in
(
select database_name, db_link
from dbs_to_monitor
left join user_db_links
on dbs_to_monitor.database_name = user_db_links.db_link
order by database_name
) loop
--Run the query if the link exists.
if links.db_link is not null then
begin
--Note the user of REPLACE and the alternative quoting mechanism, q'[...]';
--This looks a bit silly with this small example, but in a real-life query
--it avoids concatenation hell and makes the query much easier to read.
execute immediate replace(q'[
select dummy from dual@#DB_LINK#
]',
'#DB_LINK#', links.db_link)
into v_result;
dbms_output.put_line('Result: '||v_result);
--Catch errors if the links are broken or some other error happens.
exception when others then
dbms_output.put_line('Error with '||links.db_link||': '||sqlerrm);
end;
--Error if the link was not created.
--You will have to run:
--create database link LINK_NAME connect to USERNAME identified by "PASSWORD" using 'TNS_STRING';
else
dbms_output.put_line('ERROR - '||links.db_link||' does not exist!');
end if;
end loop;
end;
/
尽管如此,数据库链接还是很棒的,因为您可以在一个数据库上使用 PL/SQL 完成所有操作。您可以使用单一语言创建无代理监控解决方案,而不必担心安装和修复代理。
例如,我构建了开源程序Method5来使用数据库链接完成所有工作。安装该程序后,您可以从数百个数据库中收集结果,就像运行select * from table(m5('select * from dba_jobs'));
. 该程序可能对您的场景来说是多余的,但它表明数据库链接是完整监控解决方案所需的全部。