2012-02-02 30 views
7

Nếu một số trường hợp cùng mã đang chạy trên các máy chủ khác nhau, tôi muốn sử dụng cơ sở dữ liệu để đảm bảo quá trình không khởi động trên một máy chủ nếu nó đang chạy trên máy chủ khác.Làm cách nào để sử dụng cơ sở dữ liệu để quản lý semaphore?

Tôi có thể có thể đến với một số lệnh SQL khả thi, sử dụng xử lý giao dịch Oracle, chốt, hoặc bất cứ điều gì, nhưng tôi muốn tìm một cái gì đó đã được thử và đúng sự thật.

Năm trước, một nhà phát triển là một Wiz SQL đã có một giao dịch SQL duy nhất lấy semaphore và trả về true nếu nó nhận được, và trả về false nếu nó không nhận được nó. Sau đó, vào cuối quá trình xử lý của tôi, tôi cần chạy một giao dịch SQL khác để giải phóng semaphore. Nó sẽ được mát mẻ, nhưng tôi không biết nếu nó có thể cho một semaphore hỗ trợ cơ sở dữ liệu để có một thời gian ra. Đó sẽ là một phần thưởng lớn để có thời gian chờ!

EDIT:

Dưới đây là những gì có thể một số lệnh SQL hoàn toàn khả thi, nhưng không có thời gian chờ ngoại trừ thông qua một công việc cron hack:

--------------------------------------------------------------------- 
--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

Để tránh các bản ghi hết hạn theo cách thủ công, bạn có thể có khóa là dấu thời gian. Lấy khóa sẽ đặt dấu thời gian cho đến bây giờ. Để có được khóa, truy vấn cho khóa cần thêm điều kiện WHERE locktime <(SYSDATE - timeToExpire). Sau đó, khóa tự động hết hạn. – Glenn

+0

Cảm ơn Glenn ... timestamp thay vì Y/N là một bổ sung tốt đẹp cho các bên trên. – Dale

Trả lời

11

Bạn nên nhìn vào DBMS_LOCK. Về cơ bản, nó cho phép các cơ chế khóa enqueue mà Oracle sử dụng trong nội bộ, ngoại trừ việc nó cho phép bạn định nghĩa một loại khóa 'UL' (khóa người dùng). Khóa có thể được giữ chia sẻ hoặc độc quyền và yêu cầu khóa hoặc chuyển đổi khóa từ chế độ này sang chế độ khác, hỗ trợ hết thời gian chờ.

Tôi nghĩ rằng nó sẽ làm những gì bạn muốn.

Hy vọng điều đó sẽ hữu ích.

+0

Tôi thích điều này có thời gian chờ. Tôi chưa bao giờ sử dụng DBMS_LOCK trước đây, và tôi không thực sự là một jockey SQL, vì vậy nó có thể là một trận chiến khó khăn cho tôi để làm cho nó hoạt động, hehe. – Dale

Các vấn đề liên quan