MySQL 5 атомарный идентификатор генератора - PullRequest
3 голосов
/ 14 июня 2011

Моей логике нужно знать идентификатор таблицы перед INSERT (установка идентификатора вручную при вставке). Поскольку логика с использованием этого идентификатора используется более чем на одном сервере, хорошей идеей может быть создание mysql идентификатора, но написанная мною функция не является атомарной, поэтому вызов ее при высокой нагрузке вернет некоторые идентичные, а не уникальные числа:

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» для хранения последнего идентификатора и увеличения его для каждого нового идентификатора. Возможно, решение далеко от этого, но у меня больше нет идей.

Я забыл объяснить: Там только один сервер базы данных и n клиентов. Вышеприведенная функция не является (своего рода) поточно-ориентированной.

Ответы [ 3 ]

1 голос
/ 15 июня 2011

Вы можете использовать стратегию с чередованием идентификаторы

Каждый сервер пронумерован от 0 до n и добавляет свой номер сервера в последовательность с шагом n.Одна реализация могла бы иметь таблицу AUTO_INCREMENT для генерации идентификаторов, а затем использовать этот идентификатор в функции, подобной этой:

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
1 голос
/ 14 июня 2011

К вашему сведению, если у вас был только один сервер базы данных, это даст вам значение следующего идентификатора, который будет вставлен:

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

(отредактировано - я неправильно понял вопрос)

0 голосов
/ 28 марта 2013

Есть несколько вариантов

1) Вы можете использовать один UUID, ключ с 16 байтами (128 бит); эта стратегия работает и среди n серверов-баз данных:

выберите uuid (); (конечно .. вам понадобится поле CHAR (32) для хранения вашего UUID в виде обычного текста; MySQL некоторое время не имеет полей типа GUIID (128 бит))

Я одеваюсь, чтобы использовать сохраненную функцию, это одна из моих версий:

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 ());
  • SELECT LAS_INSERT_ID (); (SELECT в этом случае всегда будет работать, потому что происходит внутри соединения владельца)

Закрывает ваше изолированное соединение;

Это возможно делать внутри хранимых процедур / хранимых функций, но вам нужно знать, что MySQL не поддерживает несколько транзакций в одном соединении, поэтому вам нужно делать это внутри изолированного соединения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...