Loading...

Допустим у меня такой пример
php
   <?php db::exec("INSERT INTO log(ip, action) VALUES ('xxx', 'yyy')"; sleep(rand(10, 60)); # Некая ресурсоёмкая задача # А тут мне надо получить id этой записи $last = db::fetch("SELECT id FROM log ORDER BY id DESC LIMIT 1");   
Возможен ли вариант что во время "sleep" какой-нибудь другой юзер добавит еще одну свою запись и я в $last получу левый id ? Если да, то как этого избежать? Как заблокировать таблицу от изменений во время работы скрипта?
https://www.php.net/manual/ru/pdo.lastinsertid.php
Те же яйца только в профиль. Я про блокировку спросил
Something (16 авг 2023, в 11:09)
Те же яйца только в профиль. Я про блокировку спросил
командой LOCK TABLES
Потом UNLOCK после выполнения
Something (16 авг 2023, в 9:25)
Допустим у меня такой пример
php
   <?php db::exec("INSERT INTO log(ip, action) VALUES ('xxx', 'yyy')"; sleep(rand(10, 60)); # Некая ресурсоёмкая задача # А тут мне надо получить id этой записи $last = db::fetch("SELECT id FROM log ORDER BY id DESC LIMIT 1");   
Возможен ли вариант что во время "sleep" какой-нибудь другой юзер добавит еще одну свою запись и я в $last получу левый id ? Если да, то как этого избежать? Как заблокировать таблицу от изменений во время работы скрипта?
https://www.php.net/manual/en/pdo.begintransaction.php
php
   <?php db::beginTransaction(); db::exec("INSERT INTO log(ip, action) VALUES ('xxx', 'yyy')"; sleep(rand(10, 60)); $last = db::fetch("SELECT id FROM log ORDER BY id DESC LIMIT 1"); db::commit();   

________
посл. ред. 16.08.2023 в 11:19; всего 1 раз(а); by mrcatoff
FullTwo [!] (16 авг 2023, в 11:18)
командой LOCK TABLES
Потом UNLOCK после выполнения
Вот это походу то что надо. А если где-то между локом и анлоком скрипт сдохнет (например из-за fatal error), то база останется заблокированной?
mrcatoff
Адм
(16 авг 2023, в 11:19)
https://www.php.net/manual/en/pdo.begintransaction.php
php
   <?php db::beginTransaction(); db::exec("INSERT INTO log(ip, action) VALUES ('xxx', 'yyy')"; sleep(rand(10, 60)); $last = db::fetch("SELECT id FROM log ORDER BY id DESC LIMIT 1"); db::commit();   
Тоже думал про транзакции. Ты уверен что при транзакции таблица блокируется? В доках про блокировку не написано
________
посл. ред. 16.08.2023 в 11:36; всего 2 раз(а); by Something
Something (16 авг 2023, в 11:33)
Вот это походу то что надо. А если где-то между локом и анлоком скрипт сдохнет (например из-за fatal error), то база останется заблокированной?
Пока не будет unlock

Ты повесил замок, пока не откроешь не попадешь
Something (16 авг 2023, в 11:09)
Те же яйца только в профиль. Я про блокировку спросил
Это не тоже самое, ты берешь из всей таблицы записи, а в случае с функцией, тебе вернется ид самой записи и не важно, были записи или нет
https://ru.stackoverflow.com/questions/453648/Какой-id-...tid-из-pdo
Ты не только про блокировку спрашивал
Я ответила оптимальный вариант для получения ид
Зачем блокировать всю таблицу?
________
посл. ред. 16.08.2023 в 14:46; всего 1 раз(а); by Лара
Something (16 авг 2023, в 9:25)
Допустим у меня такой пример
php
   <?php db::exec("INSERT INTO log(ip, action) VALUES ('xxx', 'yyy')"; sleep(rand(10, 60)); # Некая ресурсоёмкая задача # А тут мне надо получить id этой записи $last = db::fetch("SELECT id FROM log ORDER BY id DESC LIMIT 1");   
Возможен ли вариант что во время "sleep" какой-нибудь другой юзер добавит еще одну свою запись и я в $last получу левый id ? Если да, то как этого избежать? Как заблокировать таблицу от изменений во время работы скрипта?
Да, в данном коде есть вероятность того, что во время выполнения sleep какой-либо другой пользователь добавит запись в таблицу log, и ты можеш получить неправильный ID в переменной $last. Это связано с тем, что блокировка таблицы может быть применена для предотвращения таких конфликтов. Чтобы избежать этой ситуации, ты можеш воспользоваться механизмами транзакций и блокировок в базе данных. В большинстве систем управления базами данных (СУБД) есть поддержка транзакций и блокировок, которые позволяют контролировать доступ к данным в многопользовательской среде. Тебе нужно выполнить следующие шаги: Начать транзакцию: Перед выполнением INSERT запроса начни транзакцию. Это предотвратит доступ других пользователей к данным до завершения транзакции. Выполнить INSERT внутри транзакции: Выполните INSERT запрос внутри начатой транзакции. Выполнить SELECT внутри транзакции: Также выполните SELECT запрос для получения ID внутри транзакции. Завершить транзакцию: После выполнения всех операций (включая sleep), заверши транзакцию. Это позволит другим операциям получить доступ к данным. Примерно так это может выглядеть в коде:
php
   <?php $db = new PDO("your_database_connection_details");  try {     $db->beginTransaction();          $insertQuery = "INSERT INTO log(ip, action) VALUES ('xxx', 'yyy')";     $db->exec($insertQuery);          sleep(rand(10, 60)); // Некая ресурсоёмкая задача          $selectQuery = "SELECT id FROM log ORDER BY id DESC LIMIT 1";     $last = $db->query($selectQuery)->fetchColumn();          $db->commit(); } catch (Exception $e) {     $db->rollBack();     // Обработка ошибки } ?>   
Здесь используем транзакции для обеспечения целостности данных и блокировки таблицы во время выполнения операций. Важно отметить, что использование транзакций может варьироваться в зависимости от типа базы данных, который ты используете.
Онлайн: 4
Время:
Gen. 0.1123
(c) Bym.Guru 2010-2026