sql >> Database >  >> RDS >> Mysql

mysql - een mechanisme maken dat lijkt op de reeksen van Oracle

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;



  1. Fout bij gebruik van een OLAP-verbinding:de MSOLAP-provider is niet geregistreerd op de lokale computer...

  2. SQL TUSSEN-operator voor beginners

  3. Hoe te repareren van de "datediff-functie resulteerde in een overloop" Fout in SQL Server

  4. PostgreSQL:PostgreSQL-database verwijderen via de opdrachtregel