0

我收到一批,比如 100 个项目,我需要将它们插入三个相关的 MySQL 表中:比如currentrecenthistorical。我想在单个插入语句中将每个表中的每个批次作为一个组插入以提高速度。该current表有一个自动增量主键id,我需要为每个插入的行获取它并用作主键以在recenthistorical表中插入同一行。我的想法是获取当前的 auto_increment 值current,使用 将其增加 100 alter table current AUTO_INCREMENT=,然后将 100 行插入到current我刚刚“保留”的块中以编程方式设置的 id。然后我可以使用相同的 100 个保留 id 值插入到recenthistorical表中,而无需再次从current桌子。

我的问题:有什么理由认为这是一个坏主意吗?我在网上什么也没看到。我在堆栈溢出中看到的最接近的是插入到自动增量字段中,但这并不完全相同。如果我尝试一次从多个线程执行此操作,我可以看到可能的线程问题。

我也愿意接受有关如何完成此任务的其他建议。

4

3 回答 3

0

可能存在并发问题:如果另一个连接在您获取当前值和设置新值之间插入值,您将获得重复的键。

但是,我不知道在您的情况下是否会发生这种情况,或者插入是否仅发生在上述批次中,并且永远不会有另一个并行运行的实例。

于 2013-01-18T17:42:35.050 回答
0

我认为您应该将 ID 从 3 个表中分离出来,并且使用 ALTER TABLE 听起来也很可疑。

我能想到的最合适的方法:

  • recentand中historical,添加一个引用currentID 的列;不要试图强制主 ID 相同。
  • 在 上获取 WRITE 表锁current
  • 获取的auto_increment值X。current
  • 插入您的 100 条记录;他们的 ID 现在应该从X +1 到X +100。
  • 释放表锁。
  • 在额外列中插入记录recent并使用已知 ID。historical

注意:我不确定 auto_increment 值是指向下一个 ID,还是当前的最高值。如果你使用 MAX(id) 那么你应该使用上面的代码。

于 2013-01-18T17:51:57.483 回答
0

这[有点]晚了,但如果其他人有同样的问题(就像我一样):

正如 Ethan 在他的评论中指出的那样,auto_increment 是一个用于生成唯一键的内部 MySQL 实用程序。由于您有能力在 MySQL 外部生成自己的id值,我建议从表中删除 auto_increment 开销(但保留id为 PK,以便传输到其他表)。然后,您可以将自己的id值与数据一起插入。

显然,一旦你这样做了,你就必须编写你自己的递增id值。要检索每个批次的“起点”并保持单个批次INSERT调用的速度,请创建另一个表(我将调用management),其中只有一条记录last_id,这相当于但独立于max(id)您的三个主要记录表。然后,每次准备处理一个新批次时,management使用写锁启动一个事务,批量读取management.last_idUPDATE management.last_id( last_id+1)+number,然后关闭事务。您现在可以id插入为该批次保留的顺序值,因为将来management.last_id对下一个更大的id值集的任何调用。

写锁定事务消除了任何并发问题(如 FrankPI 的回答中所述),因为任何其他尝试读取的进程都必须等待锁被移除,management并将UPDATE. 这也消除了idJvO 回答中的歧义:“...ID现在应该从 X+1 运行到 X+100”,这可能是一个危险的假设。

于 2017-05-04T21:58:45.690 回答