MySQL:在事务中截断表?

Bri*_*acy 33 mysql transactions truncate

我有一个InnoDB表需要每隔十分钟在60k到200k记录的任何地方重新填充.到目前为止,我们的方法如下:

  1. 关闭Autocommit
  2. 截断表格
  3. 执行选择查询和其他计算(使用PHP)
  4. 插入新记录
  5. 承诺

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

我想,也许我可以包住整个操作过程,包括Truncate在一个事务,这可能削减的时间长度,在此期间表出现空给用户.所以我改变了SET AUTOCOMMIT=0START TRANSCATION.

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

有什么可能导致这种情况?说实话,我根本没想到会有任何改变,因为我认为启动交易基本上只是关闭Autocommit了?

Rol*_*DBA 58

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

根据这个URL,从MySQL 5.1.32开始,TRUNCATE TABLE是DDL而不是DML,如DELETE.这意味着TRUNCATE TABLE将导致COMMIT事务块中间的隐式.因此,DELETE FROM在桌面上使用你需要清空而不是TRUNCATE TABLE.

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

  • @RolandoMySQLDBA请注意,`DELETE FROM table`和`TRUNCATE table`之间的区别不仅仅是执行时间.`TRUNCATE`也将'AUTO_INCREMENT`值重置为1,但``DELETE`不重置. (5认同)
  • "因此,请确保InnoDB经过适当调整,以处理此类回滚可能性的事务处理时间." 有关如何做到这一点的任何见解? (3认同)

Kib*_*bee 56

实现此目的的更好方法可能是将数据插入到新表中,然后在两个表上使用重命名以交换它们.单个重命名就是交换所需的全部内容,这是一个原子操作,这意味着除了显示的新数据外,用户甚至无法检测到它发生了.然后,您可以截断/删除旧数据.

  • 已经差不多一年了,只是想跟进并提到这就是我们最终做的事情,它就像一个魅力.我们创建新表,插入一大堆记录,并在更新完成后立即将它们交换出来 - 对最终用户来说它是即时的.再次感谢. (6认同)
  • 我们已经在生产中使用了这种方法一段时间,使用了原子化的RENAME table TO table_old,table_new TO table,并且效果很好。刚开始我有一种“这是骇人听闻的”的感觉,但是我看不出这种方法有什么缺点。 (2认同)