Условия гонки с mysql_last_id () - PullRequest
3 голосов
/ 10 января 2012

Большую часть дня я провел, пытаясь найти ответ на этот вопрос, но, похоже, его там нет.Мне нужна функция, которая создает строку в таблице, извлекает автоинкремент из вставленной строки, а затем использует это значение для вставки другой строки во вторую таблицу.Что-то функционально похожее на следующий php:

$mysql_query("INSERT INTO table1 SET columns='values'");
$id = mysql_insert_id();
$mysql_query("INSERT INTO table2 SET id='$id', columns='values'");

Проблема, с которой я сталкиваюсь, заключается в том, что в моем приложении одно соединение MySQL совместно используется всеми классами, поэтому я беспокоюсь, что это может привести кусловие гонки, в котором другой класс вставляет строку между выполнением 1-й и 2-й строк описанного выше.

Самое простое решение, которое я могу придумать, - это использовать любые функции, которые используют mysql_insert_id(), чтобы открыть новый, уникальный,соединение, но это кажется огромным количеством ненужных накладных расходов.Другие ответы, с которыми я играл, включают вставку уникального значения (возможно, созданного с помощью UUID()) и использование его вместо значения автоинкремента или, возможно, помещение первой вставки и вызова на LAST_INSERT_ID() в сохраненную функцию (хотя я не уверен, разрешит ли это возможное состояние гонки или нет).

Я также изучал транзакции, чтобы выяснить, могут ли они помочь, но мало информации о том, как именноmysql_insert_id() взаимодействует с ними.Насколько я могу судить, они, вероятно, здесь не помогут, так как другой INSERT, который не конфликтует ни с одной из блокировок транзакции, все еще сможет выполнить и, возможно, вызвать такое же состояние гонки.

Если предположить, что я не ошибаюсь ни с одним из вышеперечисленных (и, пожалуйста, исправьте меня, если я есть), каков наилучший способ гарантировать 100%, что вторая INSERT использует правильное значение?

Ответы [ 2 ]

7 голосов
/ 10 января 2012

PHP-скрипт выполняется линейно, а не многопоточно.
поэтому невозможно создать условие, когда один объект выполняется одновременно с другим

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

0 голосов
/ 13 июня 2014

Попробуйте использовать, если условный

пример

if(mysql_query(query)){
    $id = mysql_last_id();
    mysql_query(query using $id);
}
...