首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL 5原子id生成器

MySQL 5原子id生成器
EN

Stack Overflow用户
提问于 2011-06-14 21:12:14
回答 3查看 5.1K关注 0票数 3

在插入之前,我的逻辑需要知道表的ID (在插入时手动设置id )。因为使用此ID的逻辑位于多个服务器上,所以让mysql创建一个id可能是个好主意,但我编写的函数不是原子的,因此在高负载下调用它将返回一些标识,而不是唯一的数字:

代码语言:javascript
复制
CREATE FUNCTION `generate_document_log_id`() RETURNS BIGINT(16)
BEGIN
    DECLARE R_ID BIGINT(16);
    UPDATE document_log_sequence SET id = id + 1;
    SELECT id INTO R_ID FROM document_log_sequence;
    RETURN R_ID;
END

我使用一个表"document_log_sequence“和一个列" ID”来存储最后一个ID,并为每个新的ID递增它。

我忘了解释:只有一个数据库服务器和n个客户端。上面的函数不是(某种)线程安全的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-15 06:36:27

您可以使用交错ids的策略

每台服务器的编号从0到n,并将其服务器编号添加到按n递增的序列中。一种实现方式是使用AUTO_INCREMENT表来生成ID,然后在如下所示的函数中使用该ID:

代码语言:javascript
复制
CREATE TABLE ID_CREATOR (ID INT AUTO_INCREMENT PRIMARY KEY);

假设有3台服务器,并且此服务器是1号服务器,则此函数将为每个服务器提供一个唯一值:

代码语言:javascript
复制
CREATE FUNCTION generate_document_log_id() RETURNS INT
BEGIN
    DECLARE NUMBER_OF_SERVERS INT DEFAULT 3; -- Or read from some table
    DECLARE THIS_SERVER_ID INT DEFAULT 1; -- Or read from some table. Must be less than NUMBER_OF_SERVERS
    INSERT INTO ID_CREATOR VALUES (); -- This creates the next id
    RETURN LAST_INSERT_ID() * NUMBER_OF_SERVERS + THIS_SERVER_ID;  -- Unique numbers that interleave each other
END
票数 1
EN

Stack Overflow用户

发布于 2011-06-14 21:22:07

仅供参考,如果您只有一个数据库服务器,这将为您提供要插入的下一个id的值:

代码语言:javascript
复制
SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_NAME = 'my_table'
AND TABLE_SCHEMA = 'my_schema';

(编辑-我误解了问题)

票数 1
EN

Stack Overflow用户

发布于 2013-03-29 00:01:54

这里有一些选项

1)您可以使用一个UUID,一个16字节(128位)的密钥;此策略也适用于n个服务器数据库:

select uuid();(当然..您将需要一个字段CHAR(32)来存储纯文本形式的UUID;MySQL暂时不需要字段或键入GUIID(128位)。)

我改装成使用存储函数,这是我的一个版本:

代码语言:javascript
复制
BEGIN
DECLARE str_uuid varchar(32);
DECLARE cur1 CURSOR FOR select replace (o.oid, '-', '') from (select lower(UUID()) as oid) as o;
open cur1;
fetch cur1 into str_uuid;
close cur1;
return str_uuid;
END

2)您可以使用INT或BIGINT,但此策略仅适用于同一数据库服务器:

考虑一个具有字段my_last_id的表,dt_hr_id (my_last_id是自动递增的)启动一个隔离的连接,然后执行同样的操作

  • INSERT in (dt_hr_id) values (NOW());
  • SELECT LAS_INSERT_ID();(本例中的SELECT始终有效,因为发生在所有者连接内部)

关闭您的隔离连接;

这可以在存储过程/存储函数中完成,但是您需要知道MySQL不支持同一连接中的多个事务,因此您需要在隔离的连接中完成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6344005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档