Как залочить повторный http-запрос и не дать выполняться скрипту дальше?
Здравствуйте. Суть проблемы такова. Есть PHP-скрипт, иногда пользователь делает несколько http-запросов к нему одновременно и в БД (MySQL) летят сразу 2 запроса. Пробовал лочить через БД, т.е. вначале скрипта делаю проверку, в БД записываю 1, а в конце скрипта 0. Не помогло, так же по несколько запросов пролетают.
Как можно грамотно залочить скрипт конкретному пользователю, чтобы повторно запрос не прошёл в БД?
P.S. Скрипт как API, куки/сессии отпадают.
Slava Rozhnev, индексы есть у пользователей, вызывается UPDATE для обновления полей, после обновления, повторно запрос не проходит. А если одновременно 2 http-запроса или более, иногда проходят одновременно
Ипатьев, MySQL-сервер находится на отдельной машине, это тоже задержка.
Т.е. первый запрос не успевает сделать апдейт, чтобы залочить выполнение для второго запроса.
XiNull, вы можете толком написать, что там за запросы? Там какой-то инкремент идёт? Биллинг? Почему повторное обновление, которое в 99% процентов случаев никого не колышет, вызывает у вас катастрофу?
Вы с доктором в больнице так же разговариваете? "Ну в общем у меня болит тут кое-что, дайте мне лекарство"?
Ну создавайте /tmp/php_12.34.56.78.lock файл, в названии которого 12.34.56.78 - это IP-адрес из $_SERVER['REMOTE_ADDR']. Есть такой файл - выдаём ошибку, нет такого файла - создаём и сразу работаем, по окончании - стираем. Всё.
P.S. И не забываем регулярно чистить директорию от старых неудачно сохранившихся файлов.
MySQL-сервер находится на отдельной машине, это тоже задержка.
Т.е. первый запрос не успевает сделать апдейт, чтобы залочить выполнение для второго запроса.
update - это атомарная операция, ее нельзя не успеть сделать.
Пробовал лочить через БД, т.е. вначале скрипта делаю проверку, в БД записываю 1, а в конце скрипта 0
Вот, между проверкой и update, влезает проверка другого скрипта.
Решение - либо select for update, либо update с проверкой, одним запросом.
В идеале, вообще не лочить, но для этого нужно разбираться с бизнес-логикой.
Можно проверять по времени между запросами. первый запрос к базе произошёл, записать время. второй запрос проходит, сравнить время с первым запросом, И если разница меньше минуты (к примеру), то не выполнять запрос к базе данных.