You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求Oracle端在ORA-01000错误发生时转储打开游标至表

解决ORA-01000错误时自动转储游标详情到表的Oracle端方案

可以通过Oracle系统触发器结合系统视图实现,全程在数据库端操作,无需应用介入。以下是具体步骤:

1. 创建存储游标详情的表

在应用所属的非管理员schema下创建表,用于存储错误发生时的游标信息:

CREATE TABLE OPEN_CURSORS_DUMP (
    DUMP_TIMESTAMP TIMESTAMP DEFAULT SYSTIMESTAMP,
    SID NUMBER,
    SERIAL# NUMBER,
    USERNAME VARCHAR2(30),
    SQL_ID VARCHAR2(13),
    SQL_TEXT CLOB,
    OPEN_CURSORS_COUNT NUMBER,
    MAX_OPEN_CURSORS NUMBER
);

2. 创建捕获ORA-01000的系统触发器

由DBA在数据库端创建触发器,当ORA-01000错误触发时,自动收集当前会话的游标信息并插入上述表:

CREATE OR REPLACE TRIGGER CAPTURE_ORA_01000
AFTER SERVERERROR ON DATABASE
DECLARE
    v_sid NUMBER;
    v_serial NUMBER;
    v_username VARCHAR2(30);
    v_open_cursors NUMBER;
    v_max_cursors NUMBER;
BEGIN
    -- 仅捕获ORA-01000错误,且限制在周末触发(匹配你的场景)
    IF (SERVERERROR(1) = 1000) 
       AND (TO_CHAR(SYSTIMESTAMP, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') IN ('SAT', 'SUN')) THEN
        -- 获取触发错误的会话信息
        SELECT SID, SERIAL#, USERNAME 
        INTO v_sid, v_serial, v_username
        FROM V$SESSION
        WHERE AUDIT_SESSIONID = USERENV('SESSIONID');
        
        -- 获取当前会话的打开游标数和系统最大允许值
        SELECT VALUE INTO v_open_cursors
        FROM V$SESSTAT s
        JOIN V$STATNAME n ON s.STATISTIC# = n.STATISTIC#
        WHERE s.SID = v_sid AND n.NAME = 'opened cursors current';
        
        SELECT VALUE INTO v_max_cursors
        FROM V$PARAMETER
        WHERE NAME = 'open_cursors';
        
        -- 插入会话基本统计信息
        INSERT INTO YOUR_APP_SCHEMA.OPEN_CURSORS_DUMP (
            SID, SERIAL#, USERNAME, OPEN_CURSORS_COUNT, MAX_OPEN_CURSORS
        ) VALUES (
            v_sid, v_serial, v_username, v_open_cursors, v_max_cursors
        );
        
        -- 插入该会话所有打开游标的SQL详情
        INSERT INTO YOUR_APP_SCHEMA.OPEN_CURSORS_DUMP (
            SID, SERIAL#, USERNAME, SQL_ID, SQL_TEXT
        )
        SELECT 
            s.SID, s.SERIAL#, s.USERNAME, c.SQL_ID, t.SQL_TEXT
        FROM V$OPEN_CURSOR c
        JOIN V$SESSION s ON c.SID = s.SID AND c.SERIAL# = s.SERIAL#
        LEFT JOIN V$SQL t ON c.SQL_ID = t.SQL_ID
        WHERE s.SID = v_sid AND s.SERIAL# = v_serial;
        
        COMMIT;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        -- 避免触发器异常导致会话中断,仅记录错误信息
        DBMS_OUTPUT.PUT_LINE('Trigger CAPTURE_ORA_01000 error: ' || SQLERRM);
END;
/

3. 必要的权限配置

  • 替换SQL中的YOUR_APP_SCHEMA为实际应用使用的schema名称
  • DBA需给触发器所有者(通常是SYS)授予对目标表的插入权限:
    GRANT INSERT ON YOUR_APP_SCHEMA.OPEN_CURSORS_DUMP TO SYS;
    
  • 确保触发器所有者拥有访问V$SESSION、V$SESSTAT、V$STATNAME、V$OPEN_CURSOR、V$SQL这些系统视图的权限(SYS默认具备)

后续分析

ORA-01000错误发生后,应用可直接查询OPEN_CURSORS_DUMP表:

  • 通过OPEN_CURSORS_COUNT和MAX_OPEN_CURSORS确认是否确实超出阈值
  • 查看SQL_TEXT列,定位哪些SQL被频繁打开却未关闭,排查游标泄漏问题

内容的提问来源于stack exchange,提问作者Loïc Gammaitoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 20:32:42