Я подключаюсь к базе данных MySQL из двух разных экземпляров PHP. Первый поток добавляет новую строку, передает идентификатор новой строки во второй поток через очередь. Иногда второй поток не может найти новые данные строки, хотя теоретически он должен попасть в базу данных после того, как первые потоки закончили свою работу.
Упрощенный псевдокод выглядит примерно так:
Тема 1
$db = get_mysql_connection();
$db->beginTransaction();
$rowid = $db->query("insert data..");
$db->commit();
//For Debugging purposes only
$db->check_if_row_exists($rowid); //Always returns true
send_to_queue($rowid);
Тема 2
$rowid = fetch_from_queue();
$db = get_mysql_connection();
$db->check_if_row_exists($rowid); //Sometimes returns false;
usleep(1000000);
$db->check_if_row_exists($rowid); //Always returns true.
Я не могу понять, почему поток 1 показывает, что данные имеют действительную запись, а поток 2, который, безусловно, делает запрос иногда после потока 1, не может найти данные. Я использую транзакции для фиксации данных, это делает что-то странное?
Я использую Gearman в качестве очереди. Поток 1 запускается через Apache, а поток 2 просто запускается как отдельный процесс.
Редактировать 1:
Это происходит, когда поток 2 работает одновременно с потоком 1. Очевидно, он достигает некоторого состояния гонки с потоком 1, но я не могу понять, почему.
Редактировать 2:
Как указывает Н.Б., Innodb задерживает запись данных на диск, и, следовательно, они не видны для второго потока.
Как мне справиться с этим сценарием? Sleep / Usleep почти всегда является неоптимальным решением, так как в условиях большой нагрузки время ввода-вывода диска может увеличиться. Есть ли какой-нибудь способ «уведомить» второй поток о том, что Innodb завершил ввод / вывод диска?