2012-02-02 17 views
7

Si varias instancias del mismo código se ejecutan en diferentes servidores, me gustaría usar una base de datos para asegurarme de que un proceso no se inicie en un servidor si ya se está ejecutando en otro servidor.¿Cómo uso una base de datos para administrar un semáforo?

Probablemente podría encontrar algunos comandos de SQL viables que utilizaran el procesamiento de transacciones de Oracle, pestillos, o lo que sea, pero preferiría encontrar algo que haya sido probado y verdadero.

Hace años, un desarrollador que era un asistente SQL tenía una sola transacción SQL que tomaba el semáforo y devolvía verdadero si lo obtenía, y devolvía falso si no lo obtenía. Luego, al final de mi procesamiento, necesitaría ejecutar otra transacción SQL para liberar el semáforo. Sería genial, pero no sé si es posible que un semáforo soportado por una base de datos tenga un tiempo de espera. ¡Sería una gran ventaja tener un tiempo de espera!

EDIT:

Éstos son lo que podría haber algunos comandos SQL viables, pero sin tiempo de espera, sino por un corte tarea 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. 
--------------------------------------------------------------------- 
+2

Para evitar que los registros caduquen manualmente, puede hacer que el bloqueo sea una marca de tiempo. La adquisición del bloqueo establece la marca de tiempo hasta ahora. Para adquirir el bloqueo, la consulta para el bloqueo necesita agregar una condición WHERE locktime <(SYSDATE - timeToExpire). Entonces los bloqueos caducan automáticamente. – Glenn

+0

Gracias Glenn ... timestamp en lugar de Y/N es una buena adición a lo anterior. – Dale

Respuesta

11

usted debe buscar en DBMS_LOCK. Esencialmente, permite los mecanismos de enqueue locking que Oracle usa internamente, excepto que le permite definir un tipo de bloqueo de 'UL' (bloqueo de usuario). Los bloqueos pueden ser compartidos o exclusivos, y una solicitud para bloquear o convertir un bloqueo de un modo a otro admite un tiempo de espera.

Creo que hará lo que quiera.

Espero que ayude.

+0

Me gusta que esto tiene un tiempo de espera. Nunca antes había usado DBMS_LOCK, y realmente no soy un jinete de SQL, así que podría ser una batalla difícil para mí hacerlo funcionar, jeje. – Dale

Cuestiones relacionadas