Sau đây là một ví dụ đơn giản với FOR UPDATE khóa ý định . Khóa ngang hàng với động cơ INNODB. Mẫu hiển thị bốn hàng cho các trình tự có sẵn tiếp theo sẽ không bị Bất thường Khoảng cách INNODB nổi tiếng (trường hợp khoảng trống xảy ra sau khi sử dụng AUTO_INCREMENT không thành công).
Lược đồ:
-- drop table if exists sequences;
create table sequences
( id int auto_increment primary key,
sectionType varchar(200) not null,
nextSequence int not null,
unique key(sectionType)
) ENGINE=InnoDB;
-- truncate table sequences;
insert sequences (sectionType,nextSequence) values
('Chassis',1),('Engine Block',1),('Brakes',1),('Carburetor',1);
Mã mẫu:
START TRANSACTION; -- Line1
SELECT nextSequence into @mine_to_use from sequences where sectionType='Carburetor' FOR UPDATE; -- Line2
select @mine_to_use; -- Line3
UPDATE sequences set nextSequence=nextSequence+1 where sectionType='Carburetor'; -- Line4
COMMIT; -- Line5
Tốt nhất là bạn không có Line3
hoặc mã cồng kềnh sẽ làm trì hoãn các ứng dụng khách khác trong thời gian chờ Khóa. Có nghĩa là, lấy trình tự tiếp theo của bạn để sử dụng, thực hiện cập nhật (phần tăng dần) và COMMIT
, CÀNG SỚM CÀNG TỐT .
Ở trên trong quy trình được lưu trữ:
DROP PROCEDURE if exists getNextSequence;
DELIMITER $$
CREATE PROCEDURE getNextSequence(p_sectionType varchar(200),OUT p_YoursToUse int)
BEGIN
-- for flexibility, return the sequence number as both an OUT parameter and a single row resultset
START TRANSACTION;
SELECT nextSequence into @mine_to_use from sequences where sectionType=p_sectionType FOR UPDATE;
UPDATE sequences set nextSequence=nextSequence+1 where sectionType=p_sectionType;
COMMIT; -- get it and release INTENTION LOCK ASAP
set [email protected]_to_use; -- set the OUT parameter
select @mine_to_use as yourSeqNum; -- also return as a 1 column, 1 row resultset
END$$
DELIMITER ;
Kiểm tra:
set @myNum:= -1;
call getNextSequence('Carburetor',@myNum);
+------------+
| yourSeqNum |
+------------+
| 4 |
+------------+
select @myNum; -- 4
Sửa đổi thủ tục được lưu trữ cho phù hợp với nhu cầu của bạn, chẳng hạn như chỉ có 1 trong 2 cơ chế để truy xuất số thứ tự (tham số OUT hoặc tập kết quả). Nói cách khác, rất dễ dàng bỏ OUT
khái niệm tham số.
Nếu bạn không tuân theo bản phát hành ASAP của LOCK (điều này rõ ràng là không cần thiết sau khi cập nhật) và tiếp tục thực hiện mã tốn thời gian, trước khi phát hành, thì điều sau có thể xảy ra sau một khoảng thời gian chờ đối với các máy khách khác đang chờ trình tự số:
ERROR 1205 (HY000):Đã vượt quá thời gian chờ khóa; thử khởi động lại giao dịch
Hy vọng rằng đây không bao giờ là một vấn đề.
show variables where variable_name='innodb_lock_wait_timeout';
Trang hướng dẫn sử dụng MySQL cho innodb_lock_wait_timeout .
Trên hệ thống của tôi hiện tại, nó có giá trị là 50 (giây). Chờ đợi hơn một hoặc hai giây có lẽ là không thể chịu đựng được trong hầu hết các tình huống.
Cũng cần quan tâm trong GIAO DỊCH là phần kết quả đầu ra từ lệnh sau:
SHOW ENGINE INNODB STATUS;