sql >> Databáze >  >> RDS >> Mysql

mysql - vytvoření mechanismu podobného sekvencím Oracle

Následuje jednoduchý příklad s FOR UPDATE zámek záměru . Zámek na úrovni řady s motorem INNODB. Ukázka ukazuje čtyři řádky pro další dostupné sekvence, které nebudou trpět dobře známou anomálií mezery INNODB (případ, kdy se mezery objeví po neúspěšném použití AUTO_INCREMENT).

Schéma:

-- 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);

Ukázkový kód:

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

V ideálním případě nemáte Line3 nebo vůbec nabubřelý kód, který by zdržel ostatní klienty při čekání na zámek. To znamená, že použijte další sekvenci, proveďte aktualizaci (přírůstkovou část) a COMMIT , Co nejdříve .

Výše uvedené v uložené proceduře:

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

Upravte uloženou proceduru odpovídajícím způsobem podle svých potřeb, například mít pouze 1 ze 2 mechanismů pro načtení pořadového čísla (buď parametr OUT nebo sadu výsledků). Jinými slovy, je snadné odstranit OUT koncept parametru.

Pokud nedodržíte ASAP vydání LOCK (což samozřejmě není po aktualizaci potřeba) a před vydáním budete pokračovat v provádění časově náročného kódu, může po uplynutí časového limitu pro ostatní klienty čekající na sekvenci dojít k následujícímu:číslo:

ERROR 1205 (HY000):Překročena doba čekání na zámek; zkuste restartovat transakci

Doufejme, že to nikdy nebude problém.

show variables where variable_name='innodb_lock_wait_timeout';

Manuální stránka MySQL pro innodb_lock_wait_timeout .

V mém systému má v tuto chvíli hodnotu 50 (sekund). Čekání delší než sekunda nebo dvě je ve většině situací pravděpodobně nesnesitelné.

Během TRANSACTIONS je také zajímavá část výstupu z následujícího příkazu:

SHOW ENGINE INNODB STATUS;



  1. Zavolejte uloženou proceduru s jinou v Oracle

  2. Jak uniknout % z dotazu python mysql

  3. Výjimka v hlavním vláknu java.sql.SQLException:Přístup odepřen uživateli ''@'localhost' (pomocí hesla:NE)

  4. Seznam uložených procedur/funkcí Příkazový řádek Mysql