3

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

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

我正在使用带有一列“id”的表“document_log_sequence”来存储最后一个 ID 并为每个新 ID 递增它。也许解决方案远非如此,但我没有更多的想法。

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

4

3 回答 3

1

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

SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_NAME = 'my_table'
AND TABLE_SCHEMA = 'my_schema';

(已编辑 - 我误解了这个问题)

于 2011-06-14T13:22:06.967 回答
1

您可以使用交错id的策略

每个服务器编号为 0 到 n,并将它们的服务器编号添加到以 n 为步长的序列中。一种实现方式是创建一个AUTO_INCREMENT用于生成 ID 的表,然后在如下函数中使用该 ID:

CREATE TABLE ID_CREATOR (ID INT AUTO_INCREMENT PRIMARY KEY);

假设有 3 台服务器并且该服务器是 1 号服务器,那么此函数将为每个服务器赋予一个唯一值:

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
于 2011-06-14T22:36:26.697 回答
0

有一些选择

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

选择 uuid(); (当然..您需要一个字段 CHAR(32) 以纯文本形式存储您的 UUID;MySQL 暂时没有字段 os type GUIID(128 bits))

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

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 是 AUTOINCREMENT)

  • INSERT INTO YourTable (dt_hr_id) 值 (NOW());
  • 选择 LAS_INSERT_ID(); (在这种情况下,SELECT 总是会起作用,因为发生在所有者连接内)

关闭您的隔离连接;

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

于 2013-03-28T16:01:54.250 回答