MySQL:在事务中截断表?

MySQL:在事务中截断表?,mysql,transactions,truncate,Mysql,Transactions,Truncate,我有一个InnoDB表,需要每十分钟在60k到200k记录之间的任意位置重新填充一次。到目前为止,我们的做法如下: 关闭自动提交 截断表格 执行选择查询和其他计算(使用PHP) 插入新记录 承诺 但在执行截断操作后,数据会立即被删除,并且不再从用户界面中可用。对于我们的用户来说,这相当令人不安,即使在大约30秒内脚本遇到提交操作并重新填充表 我想也许我可以将整个操作(包括Truncate)包装到事务中,这样可以缩短用户看到表为空的时间长度。因此,我将设置自动提交=0更改为开始转换 哎呀这与预期效

我有一个InnoDB表,需要每十分钟在60k到200k记录之间的任意位置重新填充一次。到目前为止,我们的做法如下:

  • 关闭自动提交
  • 截断表格
  • 执行选择查询和其他计算(使用PHP)
  • 插入新记录
  • 承诺
  • 但在执行截断操作后,数据会立即被删除,并且不再从用户界面中可用。对于我们的用户来说,这相当令人不安,即使在大约30秒内脚本遇到提交操作并重新填充表

    我想也许我可以将整个操作(包括
    Truncate
    )包装到事务中,这样可以缩短用户看到表为空的时间长度。因此,我将
    设置自动提交=0
    更改为
    开始转换

    哎呀这与预期效果相反!现在,
    TRUNCATE
    操作仍然发生在脚本的开头,但是在事务中实际执行
    INSERT
    操作需要更长的时间,因此当
    COMMIT
    操作发生并且表中的数据再次可用时,快十分钟了


    这可能是什么原因造成的?老实说,我根本不希望有任何变化,因为我的印象是启动一个事务基本上就是关闭
    Autocommit

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

    从您的描述中,我无法真正解释您的时差。我想到的唯一一件事是,实际上并没有将插入内容包装到一个事务中,而是将其循环

    SET AUTOCOMMIT=0的关键区别在于,如果它已经是0,它将不会做任何事情,而对于START TRANSACTION,您将在当前事务中启动子事务。

    根据这个URL,从MySQL 5.1.32开始,
    TRUNCATE TABLE
    是DDL,而不是DML-like-DELETE。这意味着<代码>截断表会在事务块的中间引起隐式<代码>提交>代码>。因此,对需要清空的表使用
    DELETE FROM
    ,而不是
    TRUNCATE table


    甚至
    从tblname中删除可以回滚。回滚可能需要一段时间,因此请确保InnoDB已正确调整以处理此类回滚可能性的事务时间。

    TRUNCATE
    意味着
    COMMIT
    ,这样事务就不是ACID事务。这一点如上所述

    --

    我在MySQL中使用您的方法模拟电子邮件地址的两个表的
    外部联接。结果保留在一个表中,我可以在以后快速
    内部联接

    您的方法已经有过时的数据(因为您需要
    删除
    )。因此,这里有另一种方法,它也使用过时的数据,但完全放弃了事务。更少锁定FTW


    只需插入。。。在重复密钥更新时
    并标记“更新时间”。在脚本末尾,
    删除任何带有旧“更新时间”的内容。

    这是一个非常有趣的想法。我最初的直觉反应是表面上感觉有点粗糙,但事实上它有一种优雅的简单性,它会完美地解决我的问题。但愿我自己能想到它。:)已经快一年了,我只是想跟进一下,并提到这就是我们最终要做的事情,它就像一种魅力。我们创建新表,插入大量记录,并在更新完成后立即交换它们——对最终用户来说,这似乎是即时的。再次感谢,谢谢你。我一直在努力寻找一种最好的方法来进行批量数据更新,而不需要几秒钟的时间来关闭数据库。这是一个很好的解决方法。重命名后,您也可以
    将表
    放在旧表上。我们在生产中使用这种方法已有一段时间了,使用原子
    将表重命名为旧表,将表重命名为新表
    ,效果非常好。起初,我也有同样的“这是一种黑客行为”的感觉,但我看不出这种方法有什么坏处;我真的很感谢您的澄清(和参考)!如果Kibbee没有给我这么简单的解决方案,我绝对会给你最好的。@RolandoMySQLDBA注意到
    DELETE FROM table
    TRUNCATE table
    之间的区别不仅仅在于执行时间
    TRUNCATE
    AUTO_INCREMENT
    值也重置为1,但是
    DELETE
    不重置。“因此,请确保InnoDB已正确调整,以处理此类回滚可能性的事务时间。”有关如何执行此操作的详细信息?