В механизме хранения InnoDB MySQL хранимая процедура используется для генерации значений первичного ключа в форме tbaaa000000
,
Таким образом, формат первичного ключа:
Для фиксированной длины говорят l
, первый two
символы обозначают table_name, далее m
бывают алфавиты и отдых (l-2-m
) являются числовыми (только цифры).
Хранимая процедура была закодирована для ручного увеличения самого правого m+n
кусок символов с использованием динамического SQL. Это делается путем нахождения наибольшего идентификатора (скажем, tbaaa999999
) присутствует в таблице и увеличивает его (до tbaab000000
). Под динамическим SQL я подразумеваю, что он использовался для динамического построения операторов SQL во время выполнения путем включения переменных в запрос.
Предположим, мы пытаемся сгенерировать этот первичный ключ для таблицы. Table1
, Также у нас есть другая таблица (скажем, Table2
) который ссылается на первичный ключ Table1
(Table2
имеет внешний ключ на Table1
).
Теперь форма отправляется на сервер с помощью PHP-скрипта, который вставляет данные формы в Table1
а также Table2
, Однако идентификатор первичного ключа был сгенерирован с использованием хранимой процедуры во время выполнения запроса для Table1
, но этот идентификатор, который будет одновременно требоваться даже для запроса вставки Table2
который будет неизвестен в сценарии PHP.
Кроме того, возможно, несколько клиентов пытаются получить доступ к странице, и, таким образом, скрипт PHP запускается для всех пользователей, поэтому генерируемая хранимая процедура может генерировать один и тот же идентификатор первичного ключа для нескольких пользователей.
Table1
?Table2
?ТАК поощряет меня включать то, что я пробовал, поэтому я включил свои усилия. Однако я не хочу, чтобы объем ответов был ограничен, поэтому, пожалуйста, попробуйте придумать способ, прежде чем читать мое испытание.
Мы можем вызвать процедуру из скрипта PHP, которая принимает данные вставки в качестве аргументов и генерирует идентификатор первичного ключа Table1
а также вставляет данные в обе таблицы. Однако это не удастся, поскольку вся процедура может по-прежнему генерировать один и тот же идентификатор для одновременных запросов.
Я также исследовал try-catch
метод в конце PHP-скрипта, который вызывает функцию для генерации и возврата идентификатора в PHP-скрипт. Это будет затем попытаться вставить в Table1
который потерпит неудачу, если такой же идентификатор уже существует (может быть, из-за одновременной обработки другого вставки для другого пользователя) и выбросит duplicate key exception
и попробуйте снова, таким образом, давая уникальность. Тем не менее, я не уверен в этом методе, так как он может быть неэффективным и может вызвать проблемы с производительностью.
Для этого и нужны транзакции. Псевдокод для того, что вам нужно сделать:
Если другой клиент попытается получить доступ к Таблице 1, пока это происходит, они будут заблокированы, пока транзакция не будет зафиксирована.
Других решений пока нет …