Det følgende er et simpelt eksempel med en TIL OPDATERING hensigtslås . En række-niveau lås med INNODB motor. Eksemplet viser fire rækker for næste tilgængelige sekvenser, som ikke vil lide af den velkendte INNODB Gap Anomaly (det tilfælde, hvor huller opstår efter mislykket brug af en AUTO_INCREMENT).
Skema:
-- 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);
Eksempelkode:
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
Ideelt set har du ikke en Line3
eller bloaty kode i det hele taget, som ville forsinke andre klienter på en Lock Wait. Det betyder, få din næste sekvens til brug, udfør opdateringen (den stigende del) og COMMIT
, ASAP .
Ovenstående i en lagret 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 ;
Test:
set @myNum:= -1;
call getNextSequence('Carburetor',@myNum);
+------------+
| yourSeqNum |
+------------+
| 4 |
+------------+
select @myNum; -- 4
Rediger den lagrede procedure i overensstemmelse med dine behov, såsom at have kun 1 af de 2 mekanismer til at hente sekvensnummeret (enten OUT-parameteren eller resultatsættet). Med andre ord er det nemt at droppe OUT
parameterkoncept.
Hvis du ikke overholder ASAP-udgivelsen af LOCK (hvilket naturligvis ikke er nødvendigt efter opdateringen), og fortsætter med at udføre tidskrævende kode, før udgivelsen, så kan følgende forekomme efter en timeout-periode for andre klienter, der afventer en sekvens nummer:
FEJL 1205 (HY000):Timeout for låsevent er overskredet; prøv at genstarte transaktionen
Forhåbentlig er dette aldrig et problem.
show variables where variable_name='innodb_lock_wait_timeout';
MySQL-manualside for innodb_lock_wait_timeout .
På mit system i øjeblikket har den en værdi på 50 (sekunder). En ventetid på mere end et sekund eller to er nok uudholdelig i de fleste situationer.
Også af interesse under TRANSACTIONS er den del af outputtet fra følgende kommando:
SHOW ENGINE INNODB STATUS;