【问题标题】:PHP repeatedly updating and inserting into Innodb, update not finding correct recordsPHP反复更新并插入Innodb,更新没有找到正确的记录
【发布时间】:2015-06-22 14:41:17
【问题描述】:

我正在使用 MySQL 和在 CentOS 6.6 x64 和 PHP 5.5 上运行的 InnoDB 插件版本 5.5。隔离级别设置为 REPEATABLE-READ。

我将大约 40,000 条记录摄取到一张表中。如果我只导入大约 500 条记录,则一切正常。

其中一些记录可能具有重叠的日期时间范围。如果他们这样做了,那么在 PHP 中会执行几个步骤。

要检查重叠记录,执行 SELECT,如果返回空,我可以插入新记录。如果有记录返回,则执行以下步骤。

  1. 使两条重叠记录(记录 A)中较旧的记录无效
  2. 将旧记录的非重叠部分复制到新记录(记录 C)中并插入该记录
  3. 插入两条重叠记录中较新的一条(记录 B)

当我为 40,000 个记录案例运行摄取时,我可以看到重叠的日期范围,这意味着选择查询没有返回任何内容,然后导致特殊的重叠处理没有触发。同样,在较小的摄取案例中,所有这些逻辑都可以正常工作,并且我在这两种情况下都查看了相同的特定重叠日期范围。

此时,在我看来,当下一次选择重叠检查发生时,在逻辑的下一个循环中没有看到插入提交。

我开始研究表锁定、事务和隔离级别的选项,但不确定最好的方法是什么。

【问题讨论】:

  • 您必须展示您的实际查询/php 逻辑。如果您使用可重复读取,则事务中执行读取的所有内容都应获得相同的值。
  • 各种查询故意不在事务内部,因为它们需要使用最新的实际数据。我不希望重新读取相同的数据
  • 如果没有交易在起作用,那么 read-repeatable 并没有真正进入图片...
  • 了解并感谢您的澄清。我试图弄清楚为什么循环中的第 n 次迭代正在插入数据而第 n+1 次循环没有看到该数据。查看 Locking 和 Innodb ACID 配置让我看到了隔离(错误地)。
  • MySQL PDO 驱动程序就是这样的错误(我见过更奇怪的事情发生)。如果可以,我建议您使用存储过程。或者尝试在每次迭代时手动启动和结束事务,而不是依赖自动提交(不要忘记停用模拟准备)。或者尝试通过在查询之间引入一点延迟来调整插入速度。

标签: php mysql innodb


【解决方案1】:
# For each of the 40K rows:
BEGIN;
SELECT ... FOR UPDATE;
check for overlap (etc) and adjust accordingly
COMMIT;

这需要几分钟;可以吗?

它可以在多个线程中完成——这将加快总摄取时间。

【讨论】:

  • 我已经尝试在 select、update 重叠和 insert 语句周围使用事务,但并没有解决问题。我也尝试过使用分组键拆分多个线程,这确实加快了进程,但手头的问题是重叠错误。
  • 您已经选择...进行更新? -- 对于所有行你可能会改变?
猜你喜欢
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多