Het volgende is een eenvoudig voorbeeld met een FOR UPDATE intentievergrendeling . Een rijniveauslot met de INNODB-engine. Het voorbeeld toont vier rijen voor de volgende beschikbare reeksen die geen last zullen hebben van de bekende INNODB Gap Anomaly (het geval waarin hiaten optreden na een mislukt gebruik van een AUTO_INCREMENT).
Schema:
-- 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);
Voorbeeldcode:
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
Idealiter heb je geen Line3
of opgeblazen code die andere klanten op een Lock Wait zou vertragen. Dit betekent dat u uw volgende reeks moet gebruiken, de update moet uitvoeren (het oplopende gedeelte) en COMMIT
, ZO SNEL MOGELIJK .
Het bovenstaande in een opgeslagen procedure:
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 ;
Testen:
set @myNum:= -1;
call getNextSequence('Carburetor',@myNum);
+------------+
| yourSeqNum |
+------------+
| 4 |
+------------+
select @myNum; -- 4
Pas de opgeslagen procedure dienovereenkomstig aan voor uw behoeften, zoals het hebben van slechts 1 van de 2 mechanismen voor het ophalen van het volgnummer (ofwel de OUT-parameter of de resultatenset). Met andere woorden, het is gemakkelijk om de OUT
parameterconcept.
Als u zich niet houdt aan de ASAP-release van de LOCK (wat uiteraard niet nodig is na de update), en doorgaat met het uitvoeren van tijdrovende code voorafgaand aan de release, dan kan het volgende gebeuren na een time-outperiode voor andere clients die wachten op een reeks nummer:
FOUT 1205 (HY000):Time-out voor vergrendelingswachttijd overschreden; probeer de transactie opnieuw op te starten
Hopelijk is dit nooit een probleem.
show variables where variable_name='innodb_lock_wait_timeout';
MySQL-handleidingpagina voor innodb_lock_wait_timeout .
Op mijn systeem heeft het momenteel een waarde van 50 (seconden). Een wachttijd van meer dan een seconde of twee is in de meeste situaties waarschijnlijk ondraaglijk.
Ook van belang tijdens TRANSACTIES is dat gedeelte van de uitvoer van het volgende commando:
SHOW ENGINE INNODB STATUS;