mysql LAST_INSERT_ID 带参数序列实现

标签 mysql multithreading innodb

在 mysql 中创建线程安全序列时,我遇到了 mysql 文档 - https://dev.mysql.com/doc/refman/5.6/en/information-functions.html#function_last-insert-id ,建议创建这样的序列 -

1. mysql> CREATE TABLE sequence (id INT NOT NULL);
2. mysql> INSERT INTO sequence VALUES (0);
3. mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
4. mysql> SELECT LAST_INSERT_ID();

我的问题不是步骤4,为什么我每次需要获取新id时不能直接查询序列表来获取id?像这样 - SELECT id FROM 序列;直接查询序列表与文档中建议的 LAST_INSERT_ID 相比有什么缺点吗?

我的 mysql 实现如下 -

CREATE TABLE sequence (id INT NOT NULL);
INSERT INTO sequence VALUES (0);



 DELIMITER //
 CREATE PROCEDURE nextVal(OUT nextval INT)
   BEGIN
   UPDATE sequence SET id=LAST_INSERT_ID(id+1);
   SELECT id into nextval FROM sequence;
   END //
 DELIMITER ;

要生成新的 ID,我可以使用它

   call nextVal(@output1);
   select @output1;

Edit1:在与所有回复者交谈后,更新序列创建过程,使其无锁。我还使表格更加通用,以在单个表格中容纳多个序列,并使用函数而不是过程

 CREATE TABLE sequences (
  name CHAR(20),
  id BIGINT DEFAULT 1,
  increment TINYINT,
  UNIQUE KEY(name)
);


/* Call nextval('seqname'), and it returns the next value. */
/* If the named sequence does not yet exist, it is created with initial value 1 and increment 1 */
DELIMITER //
CREATE FUNCTION nextval (seqname CHAR(20))
RETURNS BIGINT
BEGIN
INSERT INTO sequences(name,id,increment) VALUES (seqname,LAST_INSERT_ID(1),1)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id+increment);
RETURN LAST_INSERT_ID();
END
//


/* Testing */
SELECT nextval('seq1');
SELECT nextval('seq2');
insert into sequences(name,id,increment) values ('seq3', 1000, 5);
SELECT nextval('seq3');

最佳答案

如果另一个客户端同时运行您的过程,则该过程将无法工作,因为它们都在更新 sequence 表的同一行。您需要在事务中同时运行 UPDATESELECT 以防止重叠。

LAST_INSERT_ID() 在每个连接的基础上进行管理,因此每个客户端都可以获得自己的序列,而不必通过事务相互锁定。

关于mysql LAST_INSERT_ID 带参数序列实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51289470/

相关文章:

mysql - MySQL DELETE 是否在物理上重新排序 InnoDB 表?

Mysql导入远程文件到本地服务器

mysql - 将 MySQL 数据库从测试服务器复制到本地 MAMP 服务器

mysql - 数据建模 : ethnicities with parent-child relationship?

ruby - Ruby 的线程组有什么用?

mysql - 插入 InnoDB/MyISAM 记录所需时间的差异

php - InnoDB 数据库表耗时 51 秒

mysql - 如何检查mysql中更新的行

C# lock(),无论如何要获取指标?

java - 客户端线程和服务器,服务器显示客户端 1's message, then client 2' s 消息,然后 1 等