DBMS_SCHEDULER.STOP_JOB()
とforce
をfalseに設定しているとします。ドキュメントによると、これは「割り込み機構を使用してジョブを正常に停止する」ことを意味します。この「割り込みメカニズム」に関する細部はなく、単にウェブサイト上のサイトは、それ以上の洞察を必要とせずに文書を復活させるだけです。
何が起こるか見てみましょう。ここにあなたのことを模倣する手順があります。それが完了すると、T42には32のレコードがあります。
create or replace procedure p_job_tst is
n simple_integer := 1;
begin
delete from t42;
insert into t42 (stage, id) values (1, n);
commit;
for i in 1..30 loop
n := n+1;
insert into t42 (stage, id) values (2, n);
commit;
dbms_lock.sleep(2);
end loop;
n := n+1;
insert into t42 (stage, id) values (3, n);
commit;
end;
/
dbms_lock.sleep()
への呼び出しは、それが、私たちはタイピングで超高速になることなく、半ば実行中のジョブを停止することができた、分実行します。ここでの仕事は次のとおりです。
SQL> select job_name, state, run_count from dba_scheduler_jobs where job_name = 'MY_JOB1';
JOB_NAME STATE RUN_COUNT
------------------------------ --------------- ----------
MY_JOB1 SCHEDULED 2
SQL> select job_name, state, run_count from dba_scheduler_jobs where job_name = 'MY_JOB1';
JOB_NAME STATE RUN_COUNT
------------------------------ --------------- ----------
MY_JOB1 RUNNING 2
SQL> exec sys.dbms_scheduler.STOP_JOB(job_name=>'apc.my_job1', force=>false);
PL/SQL procedure successfully completed.
SQL> select job_name, state, run_count from dba_scheduler_jobs where job_name = 'MY_JOB1';
JOB_NAME STATE RUN_COUNT
------------------------------ --------------- ----------
MY_JOB1 SCHEDULED 3
SQL>
私はT42が10件のレコードを持っていた仕事を停止する前に:
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'apc.my_job1',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN p_job_tst; END;',
start_date => systimestamp + interval '10' second,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=3',
enabled => TRUE,
comments => 'StackOverflow Test');
END;
/
は、ジョブを開始しました、それが実行しているまでのは、それを停止し、待機してみましょう。 T42の現在の内容は?
SQL> r
1* select * from t42 order by stage, id
ID STAGE
---------- ----------
1 1
2 2
3 2
4 2
5 2
6 2
7 2
8 2
9 2
10 2
11 2
ID STAGE
---------- ----------
12 2
12 rows selected.
SQL>
したがって、ジョブは正常に停止しましたが、手順の最後には停止しませんでした。これは、割り込みメカニズムが、ロックや長時間実行されているプロセスのないきれいなブレークポイントを探すかのようです。あなたのコードと同じように、私のコードにはこのようなブレークポイントがたくさんあります。各commit
はトランザクションを終了し、ロックを解放します。
あなたの仕事を「優雅に」止めるのは簡単だと思うので、スケジューラーの視点からは良いです。もちろん、アプリケーションの観点からは完全な悪夢です。その仕事は、で不明な状態にあります。作業の一部は完了し、コミットされ、一部は失われてしまいます。どのくらいのものがどれくらいのものかを判断する簡単な方法はなく、その間にデータベースが矛盾した状態になる可能性があります。
commit
ステートメントの発行に関連するベストプラクティスがあります。単位作業の最後にcommit
を1回入力します。バックグラウンドジョブはUnit Of Workですので、終了する直前にcommit
という文が1つ必要です(ブロックには例外ハンドラセクションがないと仮定します)。
終了点は最後の行の後にあります。 –
dbms_schedulerのジョブが作成され有効化され、実行されました。 Pl/SQLブロックがまだ実行中の場合、ジョブを停止することができます。それ以外の場合は、終了します。 stop_jobプロシージャの強制オプションを確認します。これは、実際にジョブをある種「殺す」特権を必要とするためです。これのデフォルトはforce => falseで、これは割り込みメカニズムを使用します。 – g00dy
@a_horse_with_no_name - 私はToruがstop_jobを発行すると、コードが実際にどこから終了するのか知りたいと思うと思います。これは強制オプションとともに使用される場合、スレーブプロセスを強制終了するか、正常に停止します。 – g00dy