The following is a simple FOR UPDATE intent lockout example. Row level lock with INNODB engine. The example shows four lines for the following available sequences that will not suffer from the known INNODB gap anomaly (the case when spaces occur after unsuccessful use of AUTO_INCREMENT).
Scheme:
-- 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);
Code example:
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
Ideally, you don't have a Line3 or bloaty code that delays other clients in standby lock mode. Meaning: use the following sequence, perform the update (incremental part) and COMMIT , ASAP .
The above procedure is stored:
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 p_YoursToUse=@mine _to_use; -- set the OUT parameter select @mine_to_use as yourSeqNum; -- also return as a 1 column, 1 row resultset END$$ DELIMITER ;
Test:
set @myNum:= -1; call getNextSequence('Carburetor',@myNum); +------------+ | yourSeqNum | +------------+ | 4 | +------------+ select @myNum; -- 4
Modify the stored procedure accordingly for your needs, for example, having only one of two mechanisms for retrieving the serial number (either the OUT parameter or the result set). In other words, it is easy to abandon the concept of parameter OUT .
If you do not adhere to the ASAP LOCK release (which obviously is not needed after the upgrade), and proceed with the execution of time-consuming code before the release, then after a waiting period for other clients the following may happen: waiting for the sequence number:
ERROR 1205 (HY000): lock timeout has been exceeded; try restarting the deal
Hope this will never be a problem.
show variables where variable_name='innodb_lock_wait_timeout';
MySQL man page for innodb_lock_wait_timeout .
On my system, it currently has a value of 50 (seconds). An expectation of more than a second or a second is probably unbearable in most situations.
In addition, the interest during transactions is that the section is derived from the following command:
SHOW ENGINE INNODB STATUS;