需要监控来自不同DBLink的无效对象

问题描述 投票:0回答:1

我必须制作一个监视器来检测不同 DBlink 的无效对象。

我尝试过在每个 DBLink 的不同文件中使用代码

-- Enable logging of results to a specific file
SPOOL C:\route

SET SERVEROUTPUT ON

DECLARE
    v_count NUMBER := 0;
    -- Define a record type to store details of invalid objects
    TYPE obj_details_type IS RECORD (
        owner         VARCHAR2(100),
        object_name   VARCHAR2(100),
        status        VARCHAR2(100),
        object_type   VARCHAR2(100)
    );
    -- Define a table type to store the details of invalid objects
    TYPE obj_details_table IS TABLE OF obj_details_type;
    -- Declare a variable to store details of invalid objects
    obj_details_list obj_details_table := obj_details_table();
BEGIN
    -- Get details of invalid objects
    FOR obj IN (SELECT owner, object_name, status, object_type
                FROM dba_objects@DBLINK
                WHERE status = 'INVALID') LOOP
        -- Increase the counter
        v_count := v_count + 1;
        -- Store details in a collection
        obj_details_list.EXTEND;
        obj_details_list(obj_details_list.LAST) := obj_details_type(obj.owner, obj.object_name, obj.status, obj.object_type);
    END LOOP;

    -- Show the number of invalid objects
    DBMS_OUTPUT.PUT_LINE('No: of invalid objects: ' || v_count);

    -- Show results as a table if there are invalid objects
    IF v_count > 0 THEN
        -- Print column headers with lines and separations
        DBMS_OUTPUT.PUT_LINE('DBLINK: - DATE, TIME: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));
        DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
        DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
        DBMS_OUTPUT.PUT_LINE('|' || RPAD('OWNER', 19) || '|' || RPAD('OBJECT NAME', 30) || '|' || RPAD('STATUS', 7) || ' |' || 'OBJECT TYPE' || ' |');
        DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
        
        -- Show details of invalid objects stored in the collection
        FOR i IN 1..obj_details_list.COUNT LOOP
            -- Imprimir cada fila en formato tabular con líneas y separaciones
            DBMS_OUTPUT.PUT_LINE('|' || RPAD(obj_details_list(i).owner, 19) || '|' || RPAD(obj_details_list(i).object_name, 30) || ' |' || RPAD(obj_details_list(i).status, 7) || ' |' || obj_details_list(i).object_type || ' |');
            DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
        END LOOP;
    ELSE
        DBMS_OUTPUT.PUT_LINE('No invalid objects were found.');
    END IF;

    -- Close the database link
    EXECUTE IMMEDIATE 'ALTER SESSION CLOSE DATABASE LINK DBLINK';
END;
/

SET SERVEROUTPUT OFF

-- Disable results recording
SPOOL OFF

问题是日志显示,打开链接的最大数量是 4,这就是为什么我在每个文件中添加

EXECUTE IMMEDIATE 'ALTER SESSION CLOSE DATABASE LINK DBLINK
但日志显示:

ERROR in line 1:
ORA-02080: database link is in use
ORA-06512: in line 49


    -- Define a record type to store details of invalid objects
                                   *
ERROR in line 3:
ORA-04052: An error occurred while querying the remote object
DBLINK 
ORA-00604: An error occurred at recursive SQL level 1 
ORA-02020: too many database links in use 

我在想是否有一种更简单的方法可以通过查询多个 DBLink 来实现这一点(我只有连接数据库、数据字典查询和创建数据库链接的权限)我也想知道是否有一种方法可以使第一个代码工作没有错误。有什么想法吗?

oracle monitoring sqlplus multiple-databases dblink
1个回答
0
投票

您无法关闭在尝试关闭数据库链接的同一个 PL/SQL 块中直接作为依赖项引用的数据库链接。您自己的会话就是使用它的会话,因为您仍在执行该 PL/SQL 块。解决方案是使用

EXECUTE IMMEDIATE
或引用光标
OPEN FOR
来删除依赖关系,并使用 动态 SQL 查询远程数据库。

将链接名称分配给局部变量(例如

var_my_link
)。然后是这样的:

DECLARE
var_my_link := 'DBLINK';
cur_remote sys_refcursor;

TYPE obj_details_type IS RECORD (
    owner         VARCHAR2(100),
    object_name   VARCHAR2(100),
    status        VARCHAR2(100),
    object_type   VARCHAR2(100)
);
-- Define a table type to store the details of invalid objects
TYPE obj_details_table IS TABLE OF obj_details_type;
-- Declare a variable to store details of invalid objects
obj_details_list obj_details_table := obj_details_table();

OPEN cur_remote FOR 'SELECT owner, object_name, status, object_type
                       FROM dba_objects@'||var_my_link||'
                      WHERE status = ''INVALID''';

FETCH cur_remote BULK COLLECT INTO obj_details_list;

-- do stuff

CLOSE cur_remote;

EXECUTE IMMEDIATE 'ALTER SESSION CLOSE DATABASE LINK '||var_my_link;
© www.soinside.com 2019 - 2024. All rights reserved.