@sir_genry

PHP PDO Как добиться синхронной работы COMMIT?

Всем привет!
Чтобы разъяснить суть вопроса приведу следующий кейс:
1. Выполняем в PHP скрипте №1 транзакцию, которую завершаем commit-ом
2. Посылаем сообщение в RabbitMQ.
3. Скрипт завершается
4. В это же время другой процесс (скрипт №2) слушает очередь и получает сообщение, посланное скриптом №1.
5. Скрипт №2 ищет в базе запись. которую только что создал Скрипт №1. И не находит!
6. Ждем какое-то время, запись появляется.

Вывод: Commit работает асинхронно.
Вопрос: Есть ли способ дождаться реального окончания commit-а и только после этого продолжать выполнение скрипта?
Использование различных уровней изоляции не помогают
  • Вопрос задан
  • 345 просмотров
Решения вопроса 1
@sir_genry Автор вопроса
Если кому-то будет интересно, то сообщаю, что использование PDOStatement::execute вместо PDO::commit в моем случае решило проблему.
На примере фреймворка yii2/
Было:
$transaction = \Yii::$app->db->beginTransaction();
try {
    ...
    $transaction->commit();
} catch (\Exception $exception) {
    $transaction->rollBack();
    throw $exception;
}

Стало:
\Yii::$app->db->createCommand('BEGIN TRANSACTION')->execute();
try {
    ...
    \Yii::$app->db->createCommand('COMMIT TRANSACTION')->execute();
} catch (\Exception $exception) {
    \Yii::$app->db->createCommand('ROLLBACK TRANSACTION')->execute();
    throw $exception;
}

Не совсем конечно красиво, и до конца не уверен, что это работает во всех случаях. Но все равно лучше чем искусственная задержка
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Melkij
@Melkij
PostgreSQL DBA
Для приложения commit синхронен. Если вы вышли из commit() - значит транзакция уже зафиксирована.

Проверяйте код приложения #2. Может быть вы уже в транзакции и потому не видите изменения. Может быть вы подключаетесь к асинхронной реплике
Ответ написан
Konstantin18ko
@Konstantin18ko
Стоматолог
Между 1 и 2 пунктом сделате проверку.
1. Выполняем в PHP скрипте №1 транзакцию, которую завершаем commit-ом
2. Проверяем, добавилась ли запись, если да переходим к п. 3, если нет повторяем п. 2 через 5 секунд.
3. Посылаем сообщение в RabbitMQ.
...
Ответ написан
@profaller
Во втором скрипте надо зафиксировать таймстамп снапшота, либо через COMMIT, либо надо сделать выборку с блокировкой через SELECT ... LOCK IN SHARE MODE, таким образом вы получите свежую выборку данных.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы