@sir_genry

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

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

Вывод: Commit работает асинхронно.
Вопрос: Есть ли способ дождаться реального окончания commit-а и только после этого продолжать выполнение скрипта?
Использование различных уровней изоляции не помогают
  • Вопрос задан
  • 320 просмотров
Решения вопроса 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, таким образом вы получите свежую выборку данных.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 17:06
15000 руб./за проект
19 апр. 2024, в 16:53
1000 руб./за проект
19 апр. 2024, в 16:45
5000 руб./за проект