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