2013-10-11 9 views
1

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

Вопрос в том, не меняя все мои существующие запросы, как я могу использовать ссылку между автоматически увеличивающимся ключом и 6-значным номером по соответствующему индексу во второй таблице?

Поскольку в эту таблицу требуется только один запрос, я хотел бы изменить это, чтобы все было просто. Я хотел бы запросить следующий номер во второй таблице и вставить его в столбец первичного ключа в первой таблице. Проблема, которую я предвижу, состоит в том, что два запроса могут ударить по серверу одновременно и могут возвращать тот же 6-значный номер из второй таблицы. Каковы мои возможности для решения этой проблемы в MySQL?

+2

использует 'UUID()' вариант? –

+0

@ gloomy.penguin См. Комментарий ниже – Josh

+0

Используйте GUID, как описано здесь http://stackoverflow.com/questions/412341/how-should-i-store-guid-in-mysql-tables –

ответ

1

Спасибо за предложения, но никто на самом деле не ответил на мой вопрос в его нынешнем виде.

Моя таблица контактов выглядит следующим образом:

id | pin | used 
1 123456 1 
2 258464 0 
3 842364 0 

И я использую запрос, чтобы получить следующий штырь:

SELECT id, pin FROM game_pins WHERE used = '0' ORDER BY id LIMIT 1; 

А потом я обновить эту строку SET used = '1'.

Чтобы предотвратить два человека получают один и тот же контактный я использую InnoDB сделки, которые в CodeIgniter я сделал, обернув все в:

$this->db->trans_start(); 

... 

$this->db->trans_complete(); 
+0

этот ответ лучше ответа tometzky, если вам требуется, чтобы контакты для удаленных игр никогда не использовались повторно. Если, однако, это не является обязательным требованием, вы просто теряете пространство на диске. При создании этой таблицы вам нужно будет заполнить ее случайными выводами, и, чтобы избежать дубликатов, вам нужно было бы создать несколько случайных контактов, чтобы найти уникальный, точно так же, как и tometzky. – user3338098

+0

вы говорите, что ответ tometzky должен замедляться, но время выполнения ожидается во время выполнения O (1), однако ваш ответ имеет _worst case_ time O (1), что означает, что ваш алгоритм имеет гарантии «в реальном времени», что является еще одним положительным аспект к вашему алгоритму, однако маловероятно, что вам нужна такая производительность для игры. – user3338098

1

Вместо того, чтобы делать все это, почему бы не использовать UUID? Вы можете изменить свои таблицы, добавив столбец этого типа в свои таблицы, и вам не нужно беспокоиться о создании чего-либо или отслеживании его.

https://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_uuid

+0

Проблема с UUID что это не удобно. Первичный ключ используется как способ для реальных людей перемещаться по приложению. Наличие 40-значного символьного ключа не принесет мне никаких преимуществ с пользователями. – Josh

+0

Если вы используете идентификатор для навигации, почему вы заинтересованы в том, чтобы люди его догадывались? – Schleis

+0

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

0

Ditch этот дополнительный стол и использовать только rand() генерировать случайное число между 100000 и 999999. Выберите этот случайный номер, пока вы не найдете неиспользованными. Не похоже, что вам нужно делать это очень часто, так что это не должно быть очень быстро. Но запросы будут быстрее, так как нет необходимости в дополнительном соединении.

Но помните, что это не более безопасно, чем просто автоинкремент - пользователь может просто попробовать все возможности 900k за несколько часов.

+0

К сожалению, этого нужно будет сделать часто, см. Http://stackoverflow.com/questions/19322234/mysql-using-random-number-as-primary-key?noredirect1_comment28639889_19322292 для объяснения. Использование 'rand()' до тех пор, пока не будет найдено число, которое не было использовано, будет слишком медленным. – Josh

+0

Это не должно быть проблемой. Я бы просто использовал 'rand()' до тех пор, пока около 50% процентов не будет использоваться, а затем я просто добавлю одну цифру «9» в верхний предел. Таким образом, вероятность рисования используемых чисел 'X' будет всегда меньше, чем' 1/2^X', например, получать хвосты 'X' раз подряд, бросая монету. В худшем случае вы бы попробовали дважды в среднем. – Tometzky

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