Задавайте вопросы, мы ответим
Вы не зашли.
Коллеги, приветствую!
Может кто сталкивался, но я в замешательстве.
В базу данных записывается заказ в инет-магазине. После INSERT сразу вызываю SELECT LAST_INSERT_ID(), чтобы получить номер заказа из автоинкрементного поля. И вот за последние пару месяцев второй раз LAST_INSERT_ID() возвращает ID из ДРУГОЙ(!) таблицы, в которую в этот момент что-то записывается в другой сессии другим посетителем.
Сам удивился, но факт остается фактом.
Вот две строчки из лога доступа
109.184.238.76 - - [25/Jan/2020:13:59:52 +0300] "GET /search/?search=%D0%90%D1%86%D0%B5%D1%82%D0%B0%D1%82 HTTP/1.0" 200 13909
87.117.58.119 - - [25/Jan/2020:13:59:52 +0300] "POST /processing/orderget.php HTTP/1.0" 302 20
Первая строка - поиск по сайту, и поисковый запрос записывается в таблицу fc__search. Вставился он с id 133807
Вторая - запись заказа в таблицу fc__orders, и заказ судя по оповещению, пришедшему на почту, был создан под номером 133807, хотя в таблицу он не записался, а по автоинкременту должен был иметь номер 2785.
А первый случай был в декабре, когда пришло оповещение о заказе с нереально огромным номером 11798141, сейчас посмотрел таблицы и нашел, что в одной из них действительно была запись с таким идентификатором примерно в то время, когда произошел сбой.
Версия СУБД - mariaDB 10.2.30.
Глюк MySQL?
Неактивен
Смотрите: LAST_INSERT_ID() возвращает последний id, вставленный в текущем потоке, подключенном к MySQL. Если у вас используется какой-нибудь connection pool или какое-то кэширование подключений (aka persistent connections), то в этом месте есть гонка, которую можно или выиграть, или проиграть.
Попробуйте посмотреть в эту сторону. Вероятность ошибки в БД обычно ниже, чем вероятность ошибки в собственном коде.
Также удобно использовать https://www.php.net/manual/ru/mysqli.insert-id.php вместо отдельного запроса.
Неактивен
paulus написал:
Смотрите: LAST_INSERT_ID() возвращает последний id, вставленный в текущем потоке, подключенном к MySQL. Если у вас используется какой-нибудь connection pool или какое-то кэширование подключений (aka persistent connections), то в этом месте есть гонка, которую можно или выиграть, или проиграть.
Попробуйте посмотреть в эту сторону. Вероятность ошибки в БД обычно ниже, чем вероятность ошибки в собственном коде.
Да никаких пулов или кеширований у меня нет, вполне себе примитивный код работы с базой - нагрузка на сайт небольшая, не было смысла что-то городить.
paulus написал:
Также удобно использовать https://www.php.net/manual/ru/mysqli.insert-id.php вместо отдельного запроса.
Что удобно - да, но ведь по сути эта функция все равно этот запрос выполняет после выполнения инсёрта. И сокращения интервала времени между инсёртом и запросом id скорее всего не произойдет. Так ведь?
Неактивен
Насколько я понимаю, нет, там в протоколе есть низкоуровневый метод, который не дергает запрос напрямую:
https://dev.mysql.com/doc/refman/8.0/en … rt-id.html
Если не поможет, то тогда надо выделять воспроизводимый кейс и отправлять в апстрим. Для выделения может помочь включение general log — увидите все запросы и последовательность выполнения.
Неактивен
paulus написал:
Насколько я понимаю, нет, там в протоколе есть низкоуровневый метод, который не дергает запрос напрямую:
https://dev.mysql.com/doc/refman/8.0/en … rt-id.html
А это любопытно, спасибо!
paulus написал:
Если не поможет, то тогда надо выделять воспроизводимый кейс и отправлять в апстрим. Для выделения может помочь включение general log — увидите все запросы и последовательность выполнения.
Увы , это виртуальный хостинг, там логи не включают (
Неактивен