2012-05-02 2 views
3

Так что моему приложению нужно разрешить пользователям создавать случайные буквенно-цифровые коды, такие как 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 предварительно сгенерированными кодами).

ответ

3

Если у вас уже есть таблица хранилища, я бы просто добавить столбец пользователя, а затем выполнить этот запрос:

UPDATE repository SET user_id = ? WHERE user_id IS NULL LIMIT N; 

После этого, вы можете выбрать записи снова. Это было два различных недостаток:

  • вам нужен индекс user_id
  • вы не можете использовать коды в таблице для чего-нибудь еще, но связывания его пользователей.
+0

Индекс на user_id был бы очень плохим ИМХО (но не знаю, могу ли я действительно его избежать), потому что у меня есть только несколько пользователей, поэтому индекс не будет таким избирательным. Что именно вы имеете в виду со второй точкой, когда у меня больше нет столбцов? Было бы хорошо, если бы таблица была '(код VARCHAR, пользовательский INT, созданный DATE, используемый DATE, цвет VARCHAR)? – xrstf

+0

Но, тем не менее, мне очень нравится простота. Я просто должен был убедиться, что в моей таблице всегда есть куча неиспользуемых кодов, и об этом можно позаботиться простым кроном. Нет необходимости синхронизировать две таблицы и перемещать строки от одного к другому. – xrstf

+0

Я не был уверен, сколько записей у вас есть, поэтому индекс может быть или не быть плохим :) мой второй пункт является просто теоретическим в том смысле, что вы не можете назначать коды для не-пользователей (у вас никогда не может быть этого сценария). Это по-прежнему оставляет вас, возможно, для очистки использованных записей, но это не должно быть очень сложно. –

Смежные вопросы