Следва прост пример с ЗА АКТУАЛИЗИРАНЕ заключване на намерение . Заключване на ниво ред с двигателя INNODB. Пробата показва четири реда за следващите налични последователности, които няма да страдат от добре познатата INNODB Gap Anomaly (случаят, когато се появяват пропуски след неуспешно използване на AUTO_INCREMENT).
Схема:
-- 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);
Примерен код:
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
В идеалния случай нямате Line3
или изобщо раздут код, който би забавил други клиенти при изчакване на заключване. Това означава, че трябва да използвате следващата си последователност, извършете актуализацията (нарастващата част) и COMMIT
, ВЪЗМОЖНО БЪРЗО .
Гореното в съхранена процедура:
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 ;
Тест:
set @myNum:= -1;
call getNextSequence('Carburetor',@myNum);
+------------+
| yourSeqNum |
+------------+
| 4 |
+------------+
select @myNum; -- 4
Променете съхранената процедура според нуждите си, като например да имате само 1 от 2-та механизма за извличане на поредния номер (или параметър OUT, или набор от резултати). С други думи, лесно е да се отървете от OUT
концепция за параметри.
Ако не се придържате към пускането на LOCK ASAP (което очевидно не е необходимо след актуализацията) и продължите да изпълнявате отнемащ време код преди освобождаването, тогава след период на изчакване може да се случи следното за други клиенти, които чакат последователност номер:
ГРЕШКА 1205 (HY000):Времето за изчакване на заключване е превишено; опитайте да рестартирате транзакцията
Дано това никога не е проблем.
show variables where variable_name='innodb_lock_wait_timeout';
Страница с ръководство на MySQL за innodb_lock_wait_timeout .
В моята система в момента има стойност 50 (секунди). Чакането от повече от секунда или две вероятно е непоносимо в повечето ситуации.
Интерес по време на ТРАНЗАКЦИИ също представлява този раздел от изхода от следната команда:
SHOW ENGINE INNODB STATUS;