Mysql
 sql >> база данни >  >> RDS >> Mysql

mysql - създаване на механизъм, подобен на последователностите на Oracle

Следва прост пример с ЗА АКТУАЛИЗИРАНЕ заключване на намерение . Заключване на ниво ред с двигателя INNODB. Пробата показва четири реда за следващите налични последователности, които няма да страдат от добре познатата INNODB Gap Anomaly (случаят, когато се появяват пропуски след неуспешно използване на AUTO_INCREMENT).

Схема:

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

Примерен код:

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

В идеалния случай нямате Line3 или изобщо раздут код, който би забавил други клиенти при изчакване на заключване. Това означава, че трябва да използвате следващата си последователност, извършете актуализацията (нарастващата част) и COMMIT , ВЪЗМОЖНО БЪРЗО .

Гореното в съхранена процедура:

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 ;

Тест:

set @myNum:= -1;
call getNextSequence('Carburetor',@myNum);
+------------+
| yourSeqNum |
+------------+
|          4 |
+------------+
select @myNum; -- 4

Променете съхранената процедура според нуждите си, като например да имате само 1 от 2-та механизма за извличане на поредния номер (или параметър OUT, или набор от резултати). С други думи, лесно е да се отървете от OUT концепция за параметри.

Ако не се придържате към пускането на LOCK ASAP (което очевидно не е необходимо след актуализацията) и продължите да изпълнявате отнемащ време код преди освобождаването, тогава след период на изчакване може да се случи следното за други клиенти, които чакат последователност номер:

ГРЕШКА 1205 (HY000):Времето за изчакване на заключване е превишено; опитайте да рестартирате транзакцията

Дано това никога не е проблем.

show variables where variable_name='innodb_lock_wait_timeout';

Страница с ръководство на MySQL за innodb_lock_wait_timeout .

В моята система в момента има стойност 50 (секунди). Чакането от повече от секунда или две вероятно е непоносимо в повечето ситуации.

Интерес по време на ТРАНЗАКЦИИ също представлява този раздел от изхода от следната команда:

SHOW ENGINE INNODB STATUS;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL Подреждане по номер, нула последни

  2. Как да попълним дупките в полетата за автоматично увеличение?

  3. Как да изтриете дубликати в MySQL таблица

  4. Бягство на MySQL заместващи карти

  5. Предупреждение:mysqli_query():Не можа да извлече mysqli