【问题标题】:MySQL: Truncate Table within Transaction?MySQL:在事务中截断表?
【发布时间】:2011-08-23 18:17:44
【问题描述】:

我有一个 InnoDB 表,需要在 60k 到 200k 条记录中每十分钟重新填充一次。到目前为止,我们的方法如下:

  1. 关闭自动提交
  2. 截断表格
  3. 执行选择查询和附加计算(使用 PHP)
  4. 插入新记录
  5. 提交

但在执行截断操作后,数据会立即删除,并且不再可从用户界面获得。对于我们的用户来说,这非常令人不安,即使在大约 30 秒左右的时间内脚本遇到了 Commit 操作并重新填充了表。

我想也许我可以将整个操作,包括Truncate,包装在一个事务中,这样可以减少表格对用户显示为空的时间长度.所以我把SET AUTOCOMMIT=0改成了START TRANSCATION

哎呀!这与预期的效果相反!现在TRUNCATE 操作仍然发生在脚本的开头,但是在事务中实际执行INSERT 操作需要更长,所以到COMMIT 操作需要地点和表格中的数据又可以使用了,已经快十分钟了!

什么可能导致这种情况?说实话,我根本没想到会有任何变化,因为我的印象是发起交易基本上只是关闭了Autocommit??

【问题讨论】:

    标签: mysql transactions truncate


    【解决方案1】:

    TRUNCATE 暗示COMMIT,因此事务不是 ACID 事务。上面已经提到了这一点。

    --

    我在 MySQL 中使用您的方法通过电子邮件地址模拟两个表的 OUTER JOIN。结果保留在表格中,我稍后可以快速INNER JOIN

    您的方法已经有过时的数据(因为您需要DELETE)。所以这是另一种方法,它也使用过时的数据,但完全放弃了交易。更少的锁定 FTW。

    只需INSERT... ON DUPLICATE KEY UPDATE 并标记“更新时间”。在脚本结束时,DELETE 任何具有旧“更新时间”的内容。

    【讨论】:

      【解决方案2】:

      http://dev.mysql.com/doc/refman/5.1/en/truncate-table.html

      根据这个 URL,从 MySQL 5.1.32 开始,TRUNCATE TABLE 是 DDL,而不是像 DELETE 这样的 DML。这意味着TRUNCATE TABLE 将在事务块中间产生隐含的COMMIT。因此,在需要清空的表上使用DELETE FROM 而不是TRUNCATE TABLE

      即使DELETE FROM tblname; 也可以回滚。回滚可能需要一段时间,因此请确保正确调整 InnoDB 以处理此类回滚可能性的事务时间。

      【讨论】:

      • 这是很好的信息,罗兰多;我非常感谢您的澄清(和参考)!如果 Kibbee 没有给我这么简单的解决方案,我绝对会给你最好的。
      • @RolandoMySQLDBA 请注意,DELETE FROM tableTRUNCATE table 之间的区别不仅仅在于执行时间。 TRUNCATE 也将 AUTO_INCREMENT 的值重置为 1,但 DELETE 不会。
      • "所以请确保 InnoDB 已正确调整以处理此类回滚可能性的事务时间。"关于如何做到这一点的任何见解?
      • 有趣的是,即使是导致错误的截断操作(例如,如果客户表不存在,“截断客户”)也可能导致隐式提交。
      【解决方案3】:

      根据您的描述,我无法真正解释您的时差。唯一想到的是您实际上并没有将插入包装到 one 事务中,而是循环它。

      与 SET AUTOCOMMIT=0 的主要区别在于,如果它已经为 0,则不会执行任何操作,而与 START TRANSACTION 一样,您将在当前事务中启动子事务。

      【讨论】:

        【解决方案4】:

        完成此操作的更好方法可能是将数据插入新表,然后在两个表上使用rename 以交换它们。交换只需要一个重命名,这是一个原子操作,这意味着用户甚至无法检测到它发生了,除非出现了新数据。然后您可以截断/删除旧数据。

        【讨论】:

        • 这是一个非常有趣的想法。我最初的直觉反应是它表面上感觉有点老套,但实际上它有一种优雅的简单性,它可​​以完美地解决我的问题。希望我自己能想到。 :)
        • 已经快一年了,只是想跟进并提到这是我们最终做的事情,它就像一个魅力。我们创建新表,插入一桶记录,并在更新完成后立即将它们换出——对于最终用户来说,它立即出现。再次感谢。
        • 谢谢。一直在努力寻找无需关闭数据库几秒钟即可进行批量数据更新的最佳方法。这是一个很好的解决方法。
        • 你也可以DROP TABLE重命名后的旧的。
        • 我们已经在生产中使用这种方法一段时间了,使用原子RENAME table TO table_old, table_new TO table,它运行良好。一开始我也有同样的“这很骇人听闻”的感觉,但我看不出这种方法有任何缺点。
        猜你喜欢
        • 2010-12-04
        • 1970-01-01
        • 2012-06-10
        • 2012-06-02
        • 1970-01-01
        • 1970-01-01
        • 2011-12-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多