同じコードの複数のインスタンスが異なるサーバーで実行されている場合、データベースを使用して、別のサーバーで既に実行されているプロセスがあるサーバーで開始しないようにしたいと考えています。データベースを使用してセマフォを管理するにはどうすればよいですか?
Oracleのトランザクション処理、ラッチなどを使用する実行可能なSQLコマンドが出てきている可能性がありますが、試したことがあります。
年前、SQLウィズであった開発者は、セマフォを取得した場合はtrueを返し、取得できなかった場合はfalseを返す単一のSQLトランザクションを持っていました。その後、私の処理の最後に、セマフォを解放するために別のSQLトランザクションを実行する必要があります。クールですが、データベースがサポートされているセマフォがタイムアウトする可能性があるかどうかはわかりません。それはタイムアウトを持っている巨大なボーナスでしょう!
編集:ここでは
は、いくつかの実行可能なSQLコマンドのかもしれないものではないが、cronジョブハックを通じて以外にはタイムアウト:
---------------------------------------------------------------------
--Setup
---------------------------------------------------------------------
CREATE TABLE "JOB_LOCKER" ("JOB_NAME" VARCHAR2(128 BYTE), "LOCKED" VARCHAR2(1 BYTE), "UPDATE_TIME" TIMESTAMP (6));
CREATE UNIQUE INDEX "JOB_LOCKER_PK" ON "JOB_LOCKER" ("JOB_NAME") ;
ALTER TABLE "JOB_LOCKER" ADD CONSTRAINT "JOB_LOCKER_PK" PRIMARY KEY ("JOB_NAME");
ALTER TABLE "JOB_LOCKER" MODIFY ("JOB_NAME" NOT NULL ENABLE);
ALTER TABLE "JOB_LOCKER" MODIFY ("LOCKED" NOT NULL ENABLE);
insert into job_locker (job_name, locked) values ('myjob','N');
commit;
---------------------------------------------------------------------
--Execute at the beginning of the job
--AUTOCOMMIT MUST BE OFF!
---------------------------------------------------------------------
select * from job_locker where job_name='myjob' and locked = 'N' for update NOWAIT;
--returns one record if it's ok. Otherwise returns ORA-00054. Any other thread attempting to get the record gets ORA-00054.
update job_locker set locked = 'Y', update_time = sysdate where job_name = 'myjob';
--1 rows updated. Any other thread attempting to get the record gets ORA-00054.
commit;
--Any other thread attempting to get the record with locked = 'N' gets zero results.
--You could have code to pull for that job name and locked = 'Y' and if still zero results, add the record.
---------------------------------------------------------------------
--Execute at the end of the job
---------------------------------------------------------------------
update job_locker set locked = 'N', update_time = sysdate where job_name = 'myjob';
--Any other thread attempting to get the record with locked = 'N' gets no results.
commit;
--One record returned to any other thread attempting to get the record with locked = 'N'.
---------------------------------------------------------------------
--If the above 'end of the job' fails to run (system crash, etc)
--The 'locked' entry would need to be changed from 'Y' to 'N' manually
--You could have a periodic job to look for old timestamps and locked='Y'
--to clear those.
---------------------------------------------------------------------
手動でレコードが期限切れにならないように、ロックをタイムスタンプにすることができます。ロックを取得すると、タイムスタンプが設定されます。ロックを取得するには、ロックのクエリで条件WHERE locktime <(SYSDATE - timeToExpire)を追加する必要があります。その後、ロックは自動的に期限切れになります。 – Glenn
ありがとうGlenn ... Y/Nの代わりにタイムスタンプを使うと、上のほうがいい。 – Dale