PHP / MySQL Критический раздел

Я использую PHP с таблицами PDO и InnoDB.

Я хочу, чтобы код позволял завершать только одну отправленную пользователем операцию, пользователь может отменить или завершить. Но в случае, когда пользователь публикует обе операции, я хочу, чтобы один из запросов завершился с ошибкой и откат, чего сейчас не происходит, обе завершаются без исключения / ошибка. Я думал, что удаления строки после проверки ее существования будет достаточно.

$pdo = new PDO();

try {

$pdo->beginTransaction();

$rowCheck = $pdo->query("SELECT * FROM table WHERE id=99")->rowCount();

if ($rowCheck == 0)
throw new RuntimeException("Row isn't there");

$pdo->exec("DELETE FROM table WHERE id = 99");

// either cancel, which does one bunch of queries. if (isset($_POST['cancel'])) ...
// or complete, which does another bunch of queries. if (isset($_POST['complete'])) ...
// do a bunch of queries on other tables here...

$pdo->commit();

} catch (Exception $e) {

$pdo->rollback();

throw $e;

}

Как я могу сделать отмену / завершение операций критическим разделом? Вторая операция ДОЛЖНА завершиться неудачей.

4

Решение

Код в порядке, за одним исключением: Добавить FOR UPDATE к первоначальному SELECT, Этого должно быть достаточно, чтобы заблокировать нажатие второй кнопки до первого DELETE произошло, что привело ко второму «провал».

https://dev.mysql.com/doc/refman/5.5/en/innodb-locking-reads.html

Примечание Блокировка строк для обновления с помощью SELECT FOR UPDATE применяется только
когда автокоммит отключен (либо путем начала транзакции с
START TRANSACTION или установив autocommit на 0. Если autocommit имеет значение
включено, строки, соответствующие спецификации, не блокируются.

1

Другие решения

Другое решение только для полноты:

private function getLock() {
$lock = $this->pdo->query("SELECT GET_LOCK('my_lock_name', 5)")->fetchColumn();

if ($lock != "1")
throw new RuntimeException("Lock was not gained: " . $lock);
}

private function releaseLock() {
$releaseLock = $this->pdo->query("SELECT RELEASE_LOCK('my_lock_name')")->fetchColumn();

if ($releaseLock != "1")
throw new RuntimeException("Lock not properly released " . $releaseLock);
}

MySQL GET_LOCK () документация

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector