gpt4 book ai didi

php - MySQL 对相同数据集但不同线程的荒谬行为

转载 作者:行者123 更新时间:2023-11-29 03:43:42 25 4
gpt4 key购买 nike

我正在从两个不同的 PHP 实例连接到 MySQL 数据库。第一个线程添加一个新行,通过队列将新行的“id”传递给第二个线程。 有时第二个线程无法找到新的行数据,即使理论上它应该在第一个线程完成其工作后访问数据库。

简化的伪代码看起来像

线程 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:正如 N.B. 所指出的,Innodb 延迟将数据写入磁盘,因此它对第二个线程不可见。

我应该如何处理这种情况? Sleep/Usleep 几乎总是一个次优的解决方案,因为在重负载条件下,磁盘 i/o 时间可能会增加。有什么方法可以“通知”第二个线程 Innodb 已完成其磁盘 i/o 吗?

最佳答案

从我的评论中粘贴,发现无需更改任何内容:

There are no race conditions here. Thread 1 can see its transactions and data. Thread 2 can't because they haven't reached the disk yet (no fsync call has been made yet by InnoDB). So naturally, you'll always see data from thread 1, but if it's not on the disk at the time of calling - you won't see it within thread 2. Threads 1 and 2 don't share the SAME mysql connection thread, both use a different one. So to cut it short - if not on disk, no data available. It's not on disk because InnoDB will delay the write until the drive is ready to write. That's why you see it after usleep.

关于php - MySQL 对相同数据集但不同线程的荒谬行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9705300/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com