mysql – 制作一个类似于Oracle序列的机制

MySQL提供了一个自动机制来增加loggingID。 这在很多方面都可以,但是我需要能够使用ORACLE提供的序列。 显然,为此目的创build一张桌子是毫无意义的。

解决scheme应该很简单:

1)创build一个表来托pipe所有需要的序列,

2)创build一个函数,增加一个特定的序列值并返回新的值,

3)创build一个函数,返回一个序列的当前值。

从理论上讲,它看起来很简单…但…

当增加一个序列的值时(与Oracle中的nextval大致相同),您需要阻止其他会话执行此操作(或者甚至获取当前值),直到更新完成。

两个理论选项:

a – 使用一个UPDATE语句来返回新的值,或者

b – 在UPDATE和SELECT之间locking表。

不幸的是,似乎MySQL不允许在函数/过程中locking表,并且试图在单个语句(如UPDATE … RETURNING …)中创build整个事物时,必须使用@typesvariablesfunction/程序的完成。

有没有人有这个想法/工作解决scheme?

谢谢。

以下是FOR UPDATE 意向locking的简单示例。 INNODB引擎的行级锁。 该示例显示了四行用于下一个可用序列,不会遇到众所周知的INNODB间隙exception(在使用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或笨拙的代码,这会延迟其他客户端的Lock Wait。 意思是,让你的下一个序列使用,执行更新(增量部分),并尽快 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 p_YoursToUse=@mine_to_use; -- set the OUT parameter select @mine_to_use as yourSeqNum; -- also return as a 1 column, 1 row resultset END$$ DELIMITER ; 

testing:

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

根据需要修改相应的存储过程,例如只有2个机制中的1个用于检索序列号(OUT参数或结果集)。 换句话说, OUT参数的概念很简单。

如果你不遵守LOCK的ASAP版本(在更新之后显然不需要),并且在释放之前继续执行费时的代码,那么在等待序列的其它客户端的超时期之后可以发生以下情况数:

错误1205(HY000):超出locking等待超时; 尝试重新启动事务

希望这不是问题。

 show variables where variable_name='innodb_lock_wait_timeout'; 

innodb_lock_wait_timeout的 MySQL手册页。

目前在我的系统上,它的值为50(秒)。 在大多数情况下,等待一两秒钟以上可能是无法忍受的。

在TRANSACTIONS期间也有兴趣的是以下命令的输出部分:

 SHOW ENGINE INNODB STATUS;