Можете ли вы гарантировать уникальные порядковые номера в MySQL - PullRequest
0 голосов
/ 23 февраля 2011

Итак, мы обрабатываем платежи по кредитным картам, и для каждого платежа требуется уникальный ссылочный идентификатор. Мы используем MySQL.

Существует таблица payments, в которой есть идентификатор первичного ключа с автоматическим приращением, processing_date, creation_at, updated_at. Моя проблема заключается в том, что эту запись невозможно сохранить до тех пор, пока не будет обработан платеж (этот процесс нельзя изменить из-за рабочего процесса приложений). В связи с этим мы не можем просто использовать первичный ключ, так как он не будет существовать до тех пор, пока не будет обработан платеж, и с тех пор мы добавили столбец reference_id с уникальным ограничением.

У меня вопрос: есть ли надежный метод генерации последовательного (или близкого к) числа на основе существующего столбца таблицы (т. Е. С использованием чего-то вроде MAX(reference_id) + 1), обработки платежа (с использованием curl) и вставки записи о платеже в таблицу с ранее сгенерированным reference_id, обеспечивая при этом уникальность. По существу резервирование ранее сгенерированного reference_id с базой данных.

Ответы [ 3 ]

2 голосов
/ 23 февраля 2011

Не пытайтесь основывать его на существующем столбце. Если вы получаете 2 транзакции одновременно, вы можете получить 2 транзакции с одинаковым идентификатором.

На основе UUID или отметки времени.

У меня похожая система, и идентификатор транзакции - ММДДГГЧЧММСС + случайное число из 8 цифр. Это нормально для транзакций с малым объемом, и очень маловероятно, что в течение 1 секунды будет 2 или более повторяющихся транзакций.

Многие шлюзы используют эту же схему.

UUID является самым безопасным, поскольку он гарантирует, что он уникален во всем мире.

1 голос
/ 23 февраля 2011

Вам нужна дополнительная таблица для reference_id и обновлять это значение каждый раз, когда вам нужен новый номер.Оберните все в транзакции, и вы сэкономите.Использование MySQL-переменной упрощает работу с SQL:

CREATE TABLE reference_id(
id INT NOT NULL
);
INSERT INTO reference_id (id) VALUES (1);

REVOKE INSERT, DELETE, TRUNCATE FROM [all users];

- реальная работа:

BEGIN;
SET @i = 0;
SELECT id + 1 INTO @i FROM reference_id FOR UPDATE;
UPDATE reference_id SET id = @i;
INSERT INTO other_table(ref_id, content) VALUES(@i, 'bla');
COMMIT;

Из-за выигранной блокировкине будет проблем целостности с параллелизмом, даже после ROLLBACK.Но пользователям, возможно, придется подождать.

1 голос
/ 23 февраля 2011

Вы можете добавить еще один столбец в таблицу платежей в качестве флага статуса / подтверждения.Когда платеж начинается, вы вводите значения и устанавливаете статус «запущен» (или что-то еще), таким образом, вы можете использовать автоматически созданный идентификатор.

Когда платеж завершен, вы можете установить флаг «завершен».».Если платеж отклонен, удалите строку.

Чтобы оптимизировать это, вы также можете создать вспомогательную процедуру, которая выполняется каждую ночь и удаляет строки со статусом «запущен», которые старше 2 дней или что-то подобное.

...