Tôi có một thủ tục được lưu trữ trong mysql thats để thực hiện một tác vụ cần được đồng bộ hóa sao cho nếu hai ứng dụng gọi thủ tục được lưu trữ, chỉ một người có thể truy cập một phần mã để thực hiện tác vụ , giữ cho người khác bị chặn cho đến khi người đầu tiên hoàn thành nhiệm vụ.Thực hiện thủ tục được lưu trữ đồng bộ trong mysql
DELIMITER $$
CREATE PROCEDURE SP_GEN_ID(IN NAME VARCHAR(20))
BEGIN
DECLARE maxLen int default 0;
START TRANSACTION;
#the section of code that needs to be synchronized
COMMIT
END;
$$
DELIMITER ;
Vì vậy, nếu hai ứng dụng gọi thủ tục lưu trữ cùng một lúc, tác vụ phải được đồng bộ hóa.
a. Nhưng Bắt đầu TRANSACTION và COMMIT KHÔNG đồng bộ hóa quá trình thực hiện.
b. Và KHÓA BẢNG tableA không thể được sử dụng trong quy trình lưu trữ để đảm bảo quá trình đồng bộ hóa.
c. Tôi đã cố gắng đồng bộ hóa cuộc gọi thủ tục được lưu trữ ở cấp ứng dụng. Tôi đã sử dụng
boost_interprocess scoped_lock lock();
Nó hoạt động hoàn toàn tốt đẹp trong tăng 1.41
Nhưng interprocess khóa mutex không được hỗ trợ trong thư viện tăng 1,34, đó là những gì có sẵn trong trường hợp của tôi.
Có cách nào để đồng bộ hóa phần thủ tục được lưu trữ của mã sao cho khi hai cuộc gọi được thực hiện đồng thời, một cuộc gọi bị chặn trước khi cuộc gọi khác được thực hiện?
(thêm nội dung sau) mã đã chỉnh sửa: để đưa ra ý tưởng những gì tôi đang cố gắng thực hiện trong khối được đồng bộ hóa của quy trình được lưu trữ.
Nó nhận được id được gán cuối cùng và tăng dần một id và kiểm tra xem nó không được sử dụng cho bản ghi 'tên' khác. Khi tìm thấy id hợp lệ, hãy cập nhật bảng bản ghi id được gán cuối cùng và sau đó liên kết với tên 'được cung cấp'.
DELIMITER $$
CREATE PROCEDURE SP_GEN_ID(IN NAME VARCHAR(20))
BEGIN
DECLARE maxLen int default 0;
START TRANSACTION;
#the section of code that needs to be synchronized
SELECT lastid into lastgenerated FROM DB_last_id WHERE key = 'NAME_ID';
findid_loop:
LOOP
set lastid = lastid + 1;
#this is to check whether it was assigned with someother name before.
IF not EXISTS (SELECT 1 FROM user_name_id WHERE name_id = lastgenerated) then
set nameid = lastgenerated;
set found = true;
LEAVE findid_loop;
END IF;
#for loop limit check
IF (counter < loopLimit) then
set counter = counter + 1;
ITERATE findid_loop;
ELSE
#reached the limit and not found.
LEAVE findid_loop;
END IF;
END LOOP findid_loop;
#if a valid id, update last id and assign to name.
IF (found) THEN
#update the id.
update DB_last_id set lastid = nameid where key = 'NAME_ID';
insert into user_name_id values (nameid ,name);
ELSE
#return an empty string for the application to take action on the failure.
set nameid = '';
END IF;
#end transaction here.
COMMIT
END;
$$
DELIMITER ;
Bảng của bạn sử dụng công cụ lưu trữ nào?Họ phải là InnoDB cho các giao dịch/khóa để làm việc. – eggyal
Công cụ lưu trữ là InnoDB cho các bảng. Nhưng nó vẫn có vẻ không hoạt động. Để xác minh điều này, tôi đã ngủ (15), chờ 15 giây ngay sau khi BẮT ĐẦU GIAO DỊCH. Khi tôi thực hiện các cuộc gọi đồng thời đến thủ tục được lưu trữ, cả hai dường như xuất hiện sau 15 giây. Nếu BẮT ĐẦU GIAO DỊCH đảm bảo đồng bộ hóa, thì cuộc gọi thứ hai đến thủ tục lưu trữ sẽ kết thúc sau 30 giây hoặc lâu hơn. đúng? (15 giây cho cuộc gọi đầu tiên để vượt qua, sau đó cuộc gọi thứ hai đi vào trong GIAO DỊCH BẮT ĐẦU và ngủ trong 15 giây) –
Mã chính xác bạn đang cố gắng đồng bộ hóa là gì? Nếu bạn chỉ đơn giản muốn các hoạt động SQL là nguyên tử, thực hiện chúng trong một giao dịch sẽ thực hiện điều đó. Nếu bạn đang ảnh hưởng đến trạng thái khác, như biến hệ thống, bạn sẽ cần phải có được một khóa trên một bảng/hồ sơ dành riêng cho mục đích này. Và việc thiếu một sự chậm trễ trong cuộc gọi thứ hai của bạn không nhất thiết là dấu hiệu của lỗi khóa (có thể, ví dụ như các vấn đề về bộ nhớ cache làm cho cuộc gọi thứ hai chạy nhanh hơn lần đầu tiên hoặc cuộc gọi thứ hai có thể thực hiện một lệnh khác đường dẫn đến đầu tiên). Vui lòng cung cấp mã đầy đủ. – eggyal