【问题标题】:Insert..Select into InnoDB table with commit after each insert?Insert..Select 在每次插入后提交到 InnoDB 表中?
【发布时间】:2011-05-05 23:46:29
【问题描述】:

我刚刚创建了一个新的分区表来替换一个旧的非分区表(为了安全起见重命名)。我在创建新表时将旧表中的最新数据复制到了新表中,但我仍有大约一半的数据需要复制。问题是,它是一个不间断的实时 Web 服务,每次我尝试通过 INSERT..SELECT 复制一个块时,它都坚持将其作为原子事务进行(这会消耗所有服务器的资源,将一切减慢到爬行,并可能使服务器危险地接近耗尽物理资源)。

要明确一点:OldTable 是 MyISAM。 NewTable 是 InnoDB,并按其主键“a”上的范围进行分区。两个表具有相同的字段名称。字段本身并不相同,但在它们不同的地方,NewTable 中的字段更大。

导致问题的查询如下所示:

INSERT INTO NewTable (a,b,c,d,e,f,g) 
SELECT a,b,c,d,e,f,g 
FROM OldTable 
WHERE a > 300000000 AND a <= 400000000
order by a

我希望它做的事情是:要么在每次插入后提交,要么完全放弃事务完整性,并允许脏读在发生时发生。

锁定 NewTable(可能超出插入的单行)是不可接受的。锁定 OldTable 很好,因为无论如何都不再使用它了(当然,除了 SQL 将其复制到新表)。

另外,有没有办法告诉 MySQL 以尽可能低的优先级执行此任务,并且只在其(相对)空闲时间处理任务?

【问题讨论】:

  • 如果你想提交 RBAR (Row By Agonizing Row),那么你需要一个光标。
  • 有没有中间的妥协?就像也许让 MySQL 每成百上千行提交一次?从字面上看,它不必在单行之后提交......我只是不想等待它坚持尝试一次吞下一百万行,而且总行数仍然太多如果我从文本编辑器复制它并将其粘贴到 MySQL 的命令行客户端,则将它们移动到小于一百万的块中。
  • 我还没有遇到允许您为批量插入/更新指定任意数字的 SQL 语法。
  • 你不能减少一次复制的行数吗?
  • 嗯,我可以...我只是希望有一个更优雅的解决方案,它可以通过 SQL 本身来支持。叹。有一天,我将不得不重新学习 Perl,这样我就不必构建 jarfile 并将它们上传到服务器来执行这样的一次性数据库维护任务。使用 Java 有点像租用挖掘机来移植万寿菊 ;-)

标签: mysql sql transactions insert innodb


【解决方案1】:

除了减少一次插入的行数之外,尝试将bulk_insert_buffer_size 系统变量的值增加到更适合您的情况吗?默认值为 8MB。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多