2009-02-11 24 views
5

Tôi đang cố gắng ghi lại tất cả các lỗi trong cơ sở dữ liệu của tôi vào một bảng. Vì vậy, khi người dùng sys tôi đã viết mã sau đây:Làm thế nào để phát triển một kích hoạt sau khi serverror trong Oracle?

CREATE TABLE servererror_log (
    error_datetime TIMESTAMP, 
    error_user  VARCHAR2(30), 
    db_name   VARCHAR2(9), 
    error_stack  VARCHAR2(2000), 
    captured_sql VARCHAR2(1000)); 
/
CREATE OR REPLACE TRIGGER log_server_errors 
AFTER SERVERERROR 
ON DATABASE 
DECLARE 
captured_sql VARCHAR2(1000); 
BEGIN 
    SELECT q.sql_text 
    INTO captured_sql 
    FROM gv$sql q, gv$sql_cursor c, gv$session s 
    WHERE s.audsid = audsid 
    AND s.prev_sql_addr = q.address 
    AND q.address = c.parent_handle; 

    INSERT INTO servererror_log 
    (error_datetime, error_user, db_name, 
    error_stack, captured_sql) 
    VALUES 
    (systimestamp, sys.login_user, sys.database_name, 
    dbms_utility.format_error_stack, captured_sql); 
END log_server_errors; 

Nhưng khi tôi buộc lỗi như cố gắng chọn từ một bảng không tồn tại, nó không ghi lại lỗi trong bảng.

Có cách nào để kiểm tra xem kích hoạt có kích hoạt không? Ngoài ra, tôi đã thử tạo một bảng thử nghiệm để chèn vào đó, nhưng nó cũng không hoạt động, ngay cả khi xác định trình kích hoạt là một giao dịch tự quản và cam kết bên trong trình kích hoạt.

Cảm ơn, Joaquin

Trả lời

1

Đừng truy vấn v $ sql; nhận được câu lệnh bằng cách sử dụng ora_sql_txt.

CREATE OR REPLACE TRIGGER log_server_errors 
AFTER SERVERERROR 
ON DATABASE 
DECLARE 
sql_text ora_name_list_t; 
stmt clob; 
n number; 
BEGIN 
    n := ora_sql_txt(sql_text); 
    if n > 1000 then n:= 1000; end if ; 
    FOR i IN 1..n LOOP 
    stmt := stmt || sql_text(i); 
    END LOOP; 

    INSERT INTO servererror_log 
    (error_datetime, error_user, db_name, 
    error_stack, captured_sql) 
    VALUES 
    (systimestamp, sys.login_user, sys.database_name, 
    dbms_utility.format_error_stack, stmt); 
    commit; 
END log_server_errors; 
/

Sau đó:

SQL> select * from c; 

này tạo ra:

select * from c 
       * 
ERROR at line 1: 
ORA-00942: table or view does not exist 

Đó bây giờ có thể được truy vấn:

select * from servererror_log; 

Để sản xuất:

ERROR_DATETIME 
--------------------------------------------------------------------------- 
ERROR_USER      DB_NAME 
------------------------------ --------- 
ERROR_STACK 
-------------------------------------------------------------------------------- 
CAPTURED_SQL 
-------------------------------------------------------------------------------- 
11-FEB-09 02.55.35.591259 PM 
SYS       TS.WORLD 
ORA-00942: table or view does not exist 
select * from c 
+0

nó không hoạt động. Ngoài ra tôi đã thử phương pháp này trước đây mà không có kết quả. Có vẻ như cò súng không bắn. Bất kỳ ý tưởng nào khác? Bạn có biết làm thế nào tôi có thể kiểm tra nếu một kích hoạt đã bị sa thải? Một cái gì đó giống như một cái nhìn với một cột LAST_FIRED_TIME hoặc một cái gì đó như thế. Cảm ơn Joaquin – xocasdashdash

+0

Có thể là chèn. Vấn đề là, nếu kích hoạt thất bại, nó khó nắm bắt. Tôi sẽ sử dụng UTL_FILE hoặc một thủ tục riêng biệt với giao dịch tự quản. Xem http://stackoverflow.com/questions/492705/is-there-any-way-to-log-all-failed-sql-statements-in-oracle-10g –

0

Kiểm tra tình trạng của kích hoạt của bạn và/hoặc sự tồn tại của trigger khác với:

select trigger_name, status 
from all_triggers 
where triggering_event like 'ERROR%' 

này nên kết quả thành:

TRIGGER_NAME  STATUS 
------------  ------- 
LOG_SERVER_ERRORS ENABLED 

Nếu kích hoạt không được kích hoạt hoặc kích hoạt một thất bại, nó có thể sẽ không hoạt động.

1

Để xem nếu kích hoạt được bắn, thêm một hoặc nhiều dòng để nó như thế này:

DBMS_OUTPUT.PUT_LINE('Got this far'); 

trong sqlplus, SET SERVEROUTPUT ON sau đó thực hiện một lệnh để tạo ra một lỗi. Bạn sẽ nhận được kết quả như thế này:

dev> select * from aldfjh; 
select * from aldfjh 
       * 
ERROR at line 1: 
ORA-00942: table or view does not exist 


ORA-00942: table or view does not exist 

Got this far 
0

Lưu này như ORA-00942.sql:

-- Drop trigger and ignore errors (e.g., not exists). 
DECLARE 
    existential_crisis EXCEPTION; 
    PRAGMA EXCEPTION_INIT(existential_crisis, -4080); 
BEGIN 
    EXECUTE IMMEDIATE 'DROP TRIGGER TRG_CATCH_ERRORS /*+ IF EXISTS */'; 
    EXCEPTION WHEN existential_crisis THEN 
    DBMS_OUTPUT.PUT_LINE('Ignoring non-existence.'); 
END; 
/

-- Drop table and ignore errors (e.g., not exists). 
DECLARE 
    existential_crisis EXCEPTION; 
    PRAGMA EXCEPTION_INIT(existential_crisis, -942); 
BEGIN 
    EXECUTE IMMEDIATE 'DROP TABLE TBL_ERROR_LOG /*+ IF EXISTS */'; 
    EXCEPTION WHEN existential_crisis THEN 
    DBMS_OUTPUT.PUT_LINE('Ignoring non-existence.'); 
END; 
/

-- Create the table (will not exist due to drop statement). 
CREATE TABLE TBL_ERROR_LOG (
    occurred  timestamp, 
    account  varchar2(32), 
    database_name varchar2(32), 
    stack   clob, 
    query   clob 
); 

-- Create the trigger to log the errors. 
CREATE TRIGGER TRG_CATCH_ERRORS AFTER servererror ON database 
DECLARE 
    sql_text ora_name_list_t; 
    n   number; 
    query_  clob; 
BEGIN 
    n := ora_sql_txt(sql_text); 

    IF n > 1000 THEN n := 1000; END IF; 

    FOR i IN 1 .. n LOOP 
     query_ := query_ || sql_text(i); 
    END LOOP; 

    INSERT INTO TBL_ERROR_LOG 
     (occurred, account, database_name, stack, query) 
    VALUES 
     (systimestamp, sys.login_user, sys.database_name, 
    dbms_utility.format_error_stack, query_); 
END; 
/

Run sử dụng sqlplus:

SQL> @ORA-00942.sql 
PL/SQL procedure successfully completed. 

PL/SQL procedure successfully completed. 

Table created. 

Trigger created. 

thử nghiệm nó:

select * from blargh; 
select * from TBL_ERROR_LOG; 

Đầu ra:

2017-10-20 15:15:25.061 SCHEMA XE "ORA-00942: table or view does not exist" select * from blargh 
Các vấn đề liên quan