【问题标题】:is there any way to log all failed sql statements in oracle 10g有没有办法在 oracle 10g 中记录所有失败的 sql 语句
【发布时间】:2009-01-29 18:00:37
【问题描述】:

有没有办法将oracle 10g中所有失败的sql语句记录到表或文件中?

失败是指格式错误的 sql 语句或没有表或对象权限的 sql 语句。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    您可能想使用如下审计:

    审核选择表、插入表、删除表、执行过程 通过访问 当不成功时;

    By ACCESS 是针对每条语句的(这似乎是你想要的)。按 SESSION 将在每个会话中记录一条记录(高容量环境)。

    Oracle 内置审计的开销比触发器少。其他答案包含的触发器允许您记录所需的确切信息。审计也只会捕获对现有对象的命中。如果有人在不存在的表(拼写错误或诸如此类)上进行选择,审计将无法捕捉到它。上面的触发器会。

    安全指南中的更多信息:http://download.oracle.com/docs/cd/B19306_01/network.102/b14266/auditing.htm#i1011984

    【讨论】:

    • +1 试图让这个(正确的)答案在列表中排名靠前:) - 如果 Tom K 在底部看到这个答案有很多“使用触发器”的答案,我们将永远听不到它的结局。 :)
    【解决方案2】:

    没有像 Demge 的回答那样点击系统视图,而是有一个 ora_sql_txt 函数可以给出相关的语句。

    create or replace TRIGGER log_err after servererror on schema
    DECLARE
      v_stack VARCHAR2(2000) := substr(dbms_utility.format_error_stack,1,2000);
      v_back VARCHAR2(2000);-- := substr(dbms_utility.format_error_backtrace,1,2000);
      v_num NUMBER;
      v_sql_text ora_name_list_t;
      procedure track(p_text in varchar2) is
      begin
         insert into .... values (p_text);
      end;
    begin
      v_stack := translate(v_stack,'''','"');
      track(v_stack);
      v_back := translate(v_back,'''','"');
      if v_back is not null then track(v_back); end if;
      v_num  := ora_sql_txt(v_sql_text);
      BEGIN
        FOR i IN 1..v_num LOOP
          track(to_char(i,'0000')||':'||v_sql_text(i));
        END LOOP;
      EXCEPTION
        WHEN VALUE_ERROR THEN NULL;
      END;
    end;
    

    在我自己的环境中,我实际上将“TRACK”作为使用自主事务的单独过程,而不是上面的块。

    create or replace procedure track (p_text IN VARCHAR2) IS
      PRAGMA AUTONOMOUS_TRANSACTION;
      cursor c_user is
        select   sys_context('USERENV','CLIENT_INFO')       client_info,
                 sys_context('USERENV','CURRENT_SCHEMA')    curr_schema,
                 sys_context('USERENV','CURRENT_USER')      curr_user,
                 sys_context('USERENV','DB_NAME')           db_name,
                 sys_context('USERENV','HOST')              host,
                 sys_context('USERENV','IP_ADDRESS')        ip,
                 sys_context('USERENV','OS_USER')           osuser,
                 sys_context('USERENV','SESSIONID')         sessid,
                 sys_context('USERENV','SESSION_USER')      sess_user,
                 sys_context('USERENV','TERMINAL')          terminal
      from dual;
      user_rec c_user%rowtype;
      v_mod  VARCHAR2(48);
      v_act  VARCHAR2(32);
      v_cli_info varchar2(64);
    begin
      open c_user;
      fetch c_user into user_rec;
      close c_user;
      DBMS_APPLICATION_INFO.READ_MODULE (v_mod, v_act);
      --DBMS_APPLICATION_INFO.READ_CLIENT_INFO(v_cli_info);
      insert into track_detail
        (id, track_time, detail, client_info, curr_schema, curr_user, db_name, 
         host, ip, osuser, sessid, sess_user, terminal, module, action)
      values (track_seq.nextval, systimestamp, p_text,
              user_rec.client_info, user_rec.curr_schema, user_rec.curr_user, 
              user_rec.db_name,     user_rec.host,        user_rec.ip, 
              user_rec.osuser,      user_rec.sessid,      user_rec.sess_user, 
              user_rec.terminal,    v_mod,                v_act);
      commit;
    end;
    

    【讨论】:

      【解决方案3】:

      您可以使用系统触发器来执行此操作。

      我直接从http://www.psoug.org/reference/system_trigger.html复制了这段代码。

      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;
          /
      

      【讨论】:

      • 在发生一些错误后,我使用此触发器ORA-04045: errors during recompilation/revalidation of RX_OAUTH.LOG_SERVER_ERRORS ORA-01031: insufficient privileges 收到以下错误,并且没有记录任何内容。即使对于系统用户
      猜你喜欢
      • 2012-02-01
      • 2020-07-29
      • 2011-08-26
      • 2015-02-25
      • 2012-01-22
      • 2014-10-02
      • 1970-01-01
      • 2013-09-20
      • 2019-02-02
      相关资源
      最近更新 更多