sql >> Database teknologi >  >> RDS >> Mysql

mysql - laver en mekanisme, der ligner Oracles sekvenser

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;
 



  1. 5 MySql nyttige forespørgsler under projektudvikling

  2. Gem procedurer i phpMyAdmin

  3. Hvad er det egentlig en BLOB i en DBMS sammenhæng

  4. Sådan fjerner du nul, når heltalsdelen er nul i Oracle