2012-02-02 15 views
7

Aynı kodun birkaç örneği farklı sunucularda çalışıyorsa, başka bir sunucuda çalışıyorsa bir işlemin bir sunucuda başlatılmadığından emin olmak için bir veritabanı kullanmak istiyorum.Bir semafor yönetmek için bir veritabanını nasıl kullanırım?

Muhtemelen Oracle işlem işleme, kilitleme veya herhangi bir şekilde kullanılan bazı uygulanabilir SQL komutları ile gelebilir, ancak denenmiş ve doğru olan bir şey bulmayı tercih ederim.

Yıllar önce bir SQL wiz'i olan bir geliştirici, semaforu alan ve aldığında doğru bir tek SQL işlemine sahipti ve almazsa yanlış döndü. Sonra işlemimin sonunda, semaforun serbest bırakılması için başka bir SQL işlemi çalıştırmam gerekecek. Harika olurdu, ancak veritabanı destekli bir semaforun zaman aşımına uğramasının mümkün olup olmadığını bilmiyorum. Bu bir zaman aşımı için büyük bir bonus olurdu!

DÜZENLEME:

İşte

bazı çalışılabilir SQL komutlarının ne olabileceğini, ancak bir cron işi hack yoluyla dışında hiçbir zaman aşımı:

--------------------------------------------------------------------- 
--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. 
--------------------------------------------------------------------- 
+2

Kayıtların manuel olarak sona ermesinden kaçınmak için kilidin bir zaman damgası olmasını sağlayabilirsiniz. Kilidi almak için zaman damgasını şimdi ayarlar. Kilidi almak için, kilit için sorgu WHERE kilitleme zamanı <(SYSDATE - timeToExpire) eklemek gerekiyor. Sonra kilitler otomatik olarak sona erer. – Glenn

+0

Teşekkürler Glenn ... Y/N yerine zaman damgası yukarıdakilere hoş bir ek. – Dale

cevap

11

Sen DBMS_LOCK içine bakmak gerekir. Esas olarak, Oracle'ın dahili olarak kullandığı kilitleme mekanizmalarına izin verir, ancak bir kilit tipi 'UL' (kullanıcı kilidi) tanımlamanıza izin verir. Kilitler, paylaşımlı veya özel olarak düzenlenebilir ve bir kilitleme veya bir moddan diğerine bir kilidi dönüştürmeye yönelik bir istek, bir zaman aşımını destekleyebilir.

İstediğinizi yapacağını düşünüyorum.

Bu yardımcı olur umarım.

+0

Bunun bir zaman aşımı olduğunu beğeniyorum. Daha önce hiç DBMS_LOCK kullanmamıştım ve ben gerçekten bir SQL jokey değilim, bu yüzden çalışmamı sağlamak için yokuş yukarı bir savaş olabilir, hehe. – Dale

İlgili konular