Так что моему приложению нужно разрешить пользователям создавать случайные буквенно-цифровые коды, такие как A6BU31, 38QV3B, R6RK7T. В настоящее время они состоят из 6 символов, тогда как I и O не используются (поэтому мы получили 34^6 возможностей). Эти коды затем распечатываются и используются для чего-то еще.Как реализовать безопасную транзакцию, случайную последовательность в MySQL
Теперь я должен убедиться, что многие пользователи могут «зарезервировать» до 100 кодов на запрос, поэтому пользователь A может захотеть получить 50 кодов, пользователь B хочет сгенерировать 10 и так далее. Эти коды должны быть уникальными для всех пользователей, поэтому пользователь A и пользователь B не могут оба получать код ABC123.
Мой текущий подход (с использованием PHP и MySQL), чтобы иметь два InnoDB таблицы для этого:
- один («хранилище») содержит большой список предварительно созданных кодов (с возможностью столкновений со временем увеличится, и я не хочу использовать метод try-insert-if-fail-try-another-code). В репозитории содержатся только коды и идентификатор с автоинкрементами (поэтому я могу сортировать их, см. Ниже).
- В другой таблице хранятся зарезервированные ключи (то есть код + владелец пользователя).
Всякий раз, когда пользователь хочет, чтобы зарезервировать N ключей, я планировал сделать следующее
BEGIN;
INSERT INTO revered_codes (code,user_id)
SELECT code FROM repository WHERE 1 ORDER BY id LIMIT N;
DELETE FROM repository WHERE 1 ORDER BY id LIMIT N;
COMMIT;
Этот должен работать, но я не уверен. Похоже, я создаю решение WTF.
После ввода я должен выбрать только зарезервированные коды, чтобы отобразить их пользователю. И это сложная часть, так как я действительно не знаю, как идентифицировать только зарезервированные коды после завершения моей транзакции. Я мог бы, конечно, добавить еще один столбец в мою таблицу reserved_codes
, удерживая какой-то случайный токен, но это кажется еще более WTFy.
Моим любимым решением было бы иметь случайную последовательность чисел, чтобы я мог просто выполнять операции INSERT
в таблице reserved_codes
.
Итак, как сделать эту уникальную, случайную и транзакционно-безопасную последовательность в MySQL? Одна из идей заключалась в том, чтобы иметь регулярный автоинкремент в таблице reserved_codes
и выводить значение случайного кода из этого числового столбца, но мне было интересно, есть ли лучший способ.
UPDATE: Я забыл упомянуть, что было бы advantagous иметь сравнительно небольшую таблицу зарезервированных кодов, как я потом должен найти одиночные коды снова для их обновления (reserved_codes
имеет несколько более атрибутов к ней) , Так что медленная работа с зарезервированной таблицей хороша (вместо того, чтобы иметь огромный индекс над ~ 1mio предварительно сгенерированными кодами).
Индекс на user_id был бы очень плохим ИМХО (но не знаю, могу ли я действительно его избежать), потому что у меня есть только несколько пользователей, поэтому индекс не будет таким избирательным. Что именно вы имеете в виду со второй точкой, когда у меня больше нет столбцов? Было бы хорошо, если бы таблица была '(код VARCHAR, пользовательский INT, созданный DATE, используемый DATE, цвет VARCHAR)? – xrstf
Но, тем не менее, мне очень нравится простота. Я просто должен был убедиться, что в моей таблице всегда есть куча неиспользуемых кодов, и об этом можно позаботиться простым кроном. Нет необходимости синхронизировать две таблицы и перемещать строки от одного к другому. – xrstf
Я не был уверен, сколько записей у вас есть, поэтому индекс может быть или не быть плохим :) мой второй пункт является просто теоретическим в том смысле, что вы не можете назначать коды для не-пользователей (у вас никогда не может быть этого сценария). Это по-прежнему оставляет вас, возможно, для очистки использованных записей, но это не должно быть очень сложно. –