【问题标题】:No data if queries are sent between TRUNCATE and SELECT INTO. Using MySQL innoDB如果在 TRUNCATE 和 SELECT INTO 之间发送查询,则没有数据。使用 MySQL innoDB
【发布时间】:2012-03-26 20:39:32
【问题描述】:

使用 MySQL 数据库时,我在创建存储过程和事件计时器时遇到了问题。 我创建了一个空表,通过 SELECT INTO 填充了另一个数据。 在填充之前,我截断了当前数据。它用于仅跟踪从当前日期起 2 个月内发生的日志条目。

这会将 350k+ 的日志表变成大约 750 个,这确实加快了报告查询的速度。

问题在于,如果客户端在 TRUNCATE 语句和 SELECT INTO 语句之间精确发送查询(考虑到 EVENT 设置为每 1 分钟运行一次,则该查询很有可能),查询不会返回任何行...

我研究了在运行此 PROCEDURE 时锁定表上的读取,但在 STORED PROCEDURES 中不允许锁定。

谁能想出一个(最好)不需要改造的解决方法? 我真的需要在这里指出正确的方向。

谢谢, 最大

【问题讨论】:

  • 也许我在这里有点误解了这个问题,但是在你插入的表上查询不是更有效吗?或者查询该表中的视图?
  • 效率不高。查询是从登录发送的,这意味着访问具有 350k+ 条记录的表需要大约 6 秒的时间。但是,将服务器端的表查询到特定日期范围的新表中,最终会得到大约 750 条记录。查询较小的表要快得多。视图在被查询时运行,因此它并不能真正加快速度。

标签: mysql stored-procedures locking innodb truncate


【解决方案1】:

我建议另一种方法,而不是截断表格,然后选择它...

您可以改为将新数据集选择到新表中。接下来,使用单个 RENAME 命令,将新表重命名为现有表,并将现有表重命名为某个备份名称。

RENAME TABLE existing_table TO backup_table, new_table TO existing_table;

这是一个单一的原子操作...因此客户端无法在数据被清空但重新填充之前读取数据。

或者,您可以将TRUNCATE 更改为DELETE FROM,然后将其与SELECT INTO 一起包装在事务中:

START TRANSACTION
    DELETE FROM YourTable;
    SELECT INTO YourTable...;
COMMIT

【讨论】:

  • +1 建议将 TRUNCATE 更改为 DELETE FROM,因为 TRUNCATE TABLE 是 DDL 而不是 DML。它将关闭当前事务并启动新事务(MySQL 5.0 认证学习指南第 418 页:amazon.com/MySQL-5-0-Certification-Study-Guide/dp/0672328127
  • 非常感谢您的修复!由于该表少于 1k 条记录,因此 DELETE FROM 与 TRUNCATE TABLE 的性能差异不会太大。两个好主意,我必须同时做,看看哪个最好。再次感谢迈克尔!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
  • 2017-12-03
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 2010-11-05
相关资源
最近更新 更多