0

特定の時間内に完了しないジョブを再スケジュールするオラクル手順を作成しました。

create or replace procedure kill_stuck_jobs
as
begin     
    for x in (  
            select j.sid,
                   s.spid,
                   s.serial#,
                   j.log_user,
                   j.job,
                   j.broken,
                   j.failures,
                   j.last_date,
                   j.this_date,
                   j.next_date,
                   j.next_date - j.last_date interval,
                   j.what
                  from 
                  (select 
                  djr.SID, 
                  dj.LOG_USER,
                  dj.JOB, 
                  dj.BROKEN,
                  dj.FAILURES, 
                  dj.LAST_DATE,
                  dj.LAST_SEC,
                  dj.THIS_DATE, dj.THIS_SEC, 
                  dj.NEXT_DATE, dj.NEXT_SEC, dj.INTERVAL, dj.WHAT
                  from dba_jobs dj, dba_jobs_running djr
                  where dj.job = djr.job ) j,
                  (select p.spid, s.sid, s.serial#
                  from v$process p, v$session s
                  where p.addr = s.paddr ) s
                  where j.sid = s.sid and 
                  j.next_date+15/1440 < sysdate  
        ) loop  
         EXEC DBMS_JOB.BROKEN(x.job,TRUE);
         execute immediate 'alter system disconnect session '''|| x.sid|| ',' || x.serial# || ''' immediate';
         EXEC DBMS_JOB.BROKEN(x.job,FALSE);
         dbms_output.put_line( 'Alter session done' );             
    end loop;  
end;  

しかし、この手順はエラーでコンパイルされます:

PLS-00103: Encountered the symbol "DBMS_JOB" when expecting one of the following:

   := . ( @ % ;
The symbol ":=" was substituted for "DBMS_JOB" to continue.

ここに画像の説明を入力

  • ここで、dbms_job と dbms_scheduler_job について説明しました。実際、ここでの問題は、リンクされた db を使用して具体化されたビューを作成したことですが、SQL*Net more data from dblink. 上記の手順を使用して、具体化されたビューの作成中に作成されたジョブを強制終了しました。次を使用してセッションを強制終了しています。

    create or replace procedure kill_stuck_refresh as 
     begin     
         for x in (  
                select username, osuser, sid, serial#, seconds_in_wait, 
                event, state, wait_class
                from v$session
                where username is not null 
                      and seconds_in_wait > 600 
                      and event = 'SQL*Net more data from dblink'  
            ) loop  
            execute immediate 'alter system disconnect session '''|| x.sid  
                         || ',' || x.serial# || ''' immediate';
            dbms_output.put_line( 'Alter session done' );             
         end loop;  
       end; -- end of kill_stuck_refresh; 
    
4

4 に答える 4

4

エラースタックはすべて、カーソルが無効であるという事実に由来しています。原因は ORA-00942 です。これは、テーブル名のスペルが間違っていることを意味している可能性がありますが、データ ディクショナリを使用しているため、通常は権限の問題を示しています。つまり、テーブル (またはこの場合はビュー) がスコープに存在しません。

あなたのコメントに私たちをもたらします:

「選択クエリを個別に実行できます。それは、私がそれらの特権を持っていることを意味すると思います。」

これは、あなたが権限を持っているロールに権限が付与されたことを示唆しています。SQL のロールを通じて付与されたアクセス許可を使用できますが、それらを使用してビューやストアド プロシージャなどの永続的なオブジェクトを構築することはできません。これが機能するには、ユーザーに直接付与されたビューに対する権限が必要です。回避策はありません。これが Oracle セキュリティ モデルの仕組みです。


ちなみに、これらのジョブに時間がかかりすぎる理由を調査する必要があります。これは永続的な問題だと思います (そうでなければ、なぜこれらのジョブを強制終了するためにストアド プロシージャを構築しているのですか?)。仕事を殺すことは、リソースを浪費し、有用な証拠を消し去る鈍器です。パフォーマンスの低下の根本的な原因を見つけて修正することをお勧めします。おそらく、セッションのブロックに問題があり、ロック戦略が必要です。たぶん、チューニングが不十分な SQL を持っているかもしれません。他のジョブが同時に実行されていて、すべてのリソースを使い果たしている可能性があります。その場合、適切なスケジューラが必要です。あるいは、より多くのデータ (成功の代償) を取得しただけで、ジョブを完了するためにより多くの時間を与える必要がある場合もあります。

于 2012-05-22T10:49:13.600 に答える
3

EXECこのコンテキスト (ストアド プロシージャ/関数)では必要ありません。SQL から (SQL*Plus から) ストアド プロシージャを呼び出す場合にのみ必要です。dbms_job.broken()直接電話するだけです:

...
DBMS_JOB.BROKEN(x.job,TRUE);
execute immediate 'alter system disconnect session '''|| x.sid|| ',' || x.serial# || ''' immediate';
DBMS_JOB.BROKEN(x.job,FALSE);
dbms_output.put_line( 'Alter session done' );
...
于 2012-05-22T06:11:28.940 に答える
2

@David Aldridgeが述べたように、DBMS_Schedulerは主にDBMS_Jobを置き換えることを目的としています(実際には10gから)。彼が言及しなかったのは、なぜこれが役立つのかということです。

DBMS_Scheduler は、ロギングの改善など、ジョブに対するより多くの制御を提供します。ただし、最も重要なのは、DBMS_Scheduler がmax_run_durationジョブにパラメーターを追加することです。ジョブの実行時間がその期間を超えると、ジョブは自動的に終了します (おそらく、セッションを強制終了するよりも適切な方法で)。次に、パラメーターが設定されていない限りmax_failures、ジョブは次のスケジュールされた時間に再試行されます。

現在のジョブを DBMS_Scheduler に移行できれば、コードを記述して既存の機能を提供する手間を省くことができます。

于 2012-05-22T14:52:34.800 に答える
1

Oracle 11gを使用している場合は、DBMS_JobではなくDBMS_Schedulerを使用する必要があります。最初に新しいパッケージへの移行を検討し、そのコンテキストで要件を再考してください。

于 2012-05-22T09:33:52.087 に答える