sql >> データベース >  >> RDS >> Oracle

Oracle19cOpen_cursorが問題を超えました

    最大オープンカーソルの問題の原因はわかりませんが、GV$OPEN_CURSORを使用して関連するセッションとSQLステートメントを特定することで原因を特定する方法を説明します。 。

    運が良ければ、セッションごとに開いているカーソルの数をカウントする簡単なクエリで問題をすぐに見つけることができます。以下のクエリには多くの列があります。IDEを使用すると、すべてのデータを簡単に参照できます。私の経験では、USER_NAMEやSQL_TEXTのような列を一瞥するだけで、原因を特定できます。

    select count(*) over (partition by inst_id, sid) cursors_per_session, gv$open_cursor.*
    from gv$open_cursor
    order by cursors_per_session desc, inst_id, sid;
    

    そのビューには、予想よりもカウントが大きくなる可能性のある奇妙なクエリが多数あることに注意してください。すべての再帰的でキャッシュされたクエリでは、「退屈な」セッションで50個のカーソルを使用することは珍しくありません。何百ものカーソルが開いているセッションを探しています。 (誰かが愚かにパラメータ値をデフォルトより低くした場合を除きます。)

    残念ながら、GV$OPEN_CURSOR 履歴データは含まれていません。多くのカーソルをすばやく開くタイトなループ内に例外がある場合、これらの問題はすぐに開始および停止する可能性があります。以下のPL/SQLブロックは、開いているカーソルが多数あるセッションを検出し、データを格納して終了するまで実行されます。このPL/SQLブロックは高価であり、適切な瞬間を待っている処理のセッション全体を使い果たすため、問題を見つけるために1回だけ使用してください。

    --Create table to hold the results.
    create table too_many_cursors as
    select 1 cursors_per_session, gv$open_cursor.*
    from gv$open_cursor
    where 1 = 0;
    
    
    --Write the open cursor data when a session gets more than N open cursors.
    declare
        v_open_cursor_threshold number := 50;
        v_count number;
    begin
        --Loop forever until the problem is found.
        loop
            --Count the largest numbe of open cursors.
            select max(the_count)
            into v_count
            from
            (
                select count(*) the_count
                from gv$open_cursor
                group by inst_id, sid
            );
    
            --If the threshold is reached, write the data, commit it, and quit the program.
            if v_count >= v_open_cursor_threshold then
    
                insert into too_many_cursors
                select *
                from
                (
                    select count(*) over (partition by inst_id, sid) cursors_per_session, gv$open_cursor.*
                    from gv$open_cursor
                )
                where cursors_per_session >= v_open_cursor_threshold;
                
                commit;
                
                exit;
            end if;
            
        end loop;
    end;
    /
    
    
    --Your problem should now be in this table:
    select * from too_many_cursors;
    

    監視をテストする場合は、以下のPL/SQLブロックを使用して多数のカーソルを開くことができます。

    --Open a large number of cursors in and wait for 20 seconds.
    --(Done by creating a dynamic PL/SQL block with many "open" commands with a "sleep" at the end.
    declare
        v_number_of_open_cursors number := 200;
        v_declarations clob;
        v_opens clob;
        v_sql clob;
    begin
        for i in 1 .. v_number_of_open_cursors loop
            v_declarations := v_declarations || 'v_cursor'|| i ||' sys_refcursor;' || chr(10);
            v_opens := v_opens || 'open v_cursor' || i || ' for select * from dual;';
        end loop;
    
        v_sql :=
            'declare '||chr(10)||v_declarations||chr(10)||
            'begin'||chr(10)||v_opens||chr(10)||
            'dbms_lock.sleep(20);'||chr(10)||'end;';
    
        --Print for debugging.
        --dbms_output.put_line(v_sql);
    
        execute immediate v_sql;
    end;
    /
    



    1. C#でのストアドプロシージャの出力パラメータの使用

    2. グループごとに<whatever>が最も高い/最も小さいレコードを取得します

    3. MySQLの2つのテーブルからDELETEするトリガーが必要です

    4. Hibernateが2つのテーブルに参加し、春の安らかなWebサービスでjson応答を生成しますか?