繁体   English   中英

截断条件

[英]Truncate with condition

truncate - >这会重置整个表,有没有办法通过truncate来重置特定的记录/检查条件。

例如:我想重置所有数据并在表格中保留最近30天。

谢谢。

不, TRUNCATE是全有或全无。 您可以执行DELETE FROM <table> WHERE <conditions>但这会失去TRUNCATE的速度优势。

简短的回答是否定的:MySQL 不会允许你添加一个WHERE子句的TRUNCATE语句。 这是MySQL关于TRUNCATE语句的文档

但好消息是你可以(有点)解决这个限制。

使用DELETE简单,安全,干净但缓慢的解决方案

首先,如果表足够小,只需使用DELETE语句(必须提到):

1. LOCK TABLE my_table WRITE;
2. DELETE FROM my_table WHERE my_date<DATE_SUB(NOW(), INTERVAL 1 MONTH);
3. UNLOCK TABLES;

LOCKUNLOCK语句不是强制性的,但它们可以加快速度并避免潜在的死锁。

不幸的是,如果你的表很大,这将非常慢......并且因为你正在考虑使用TRUNCATE语句,我想这是因为你的表很大。

所以这是使用TRUNCATE语句解决问题的一种方法:

使用TRUNCATE简单,快速但不安全的解决方案

1. CREATE TABLE my_table_backup AS
      SELECT * FROM my_table WHERE my_date>=DATE_SUB(NOW(), INTERVAL 1 MONTH);
2. TRUNCATE my_table;
3. LOCK TABLE my_table WRITE, my_table_backup WRITE;
4. INSERT INTO my_table SELECT * FROM my_table_backup;
5. UNLOCK TABLES;
6. DROP TABLE my_table_backup;

不幸的是,如果其他进程同时在表中插入记录,则此解决方案有点不安全:

  • 在步骤1和2之间插入的任何记录都将丢失
  • TRUNCATE语句将AUTO-INCREMENT计数器重置为零。 因此,在步骤2和3之间插入的任何记录都将具有低于旧ID的ID,甚至可能与在步骤4中插入的ID冲突(请注意,在步骤4之后, AUTO-INCREMENT计数器将返回到其正确的值) 。

不幸的是,无法锁定表并截断它。 但是我们可以(某种方式)使用RENAME解决这个限制。

使用TRUNCATE半简单,快速,安全但嘈杂的解决方案

1. RENAME TABLE my_table TO my_table_work;
2. CREATE TABLE my_table_backup AS
     SELECT * FROM my_table_work WHERE my_date>DATE_SUB(NOW(), INTERVAL 1 MONTH);
3. TRUNCATE my_table_work;
4. LOCK TABLE my_table_work WRITE, my_table_backup WRITE;
5. INSERT INTO my_table_work SELECT * FROM my_table_backup;
6. UNLOCK TABLES;
7. RENAME TABLE my_table_work TO my_table;
8. DROP TABLE my_table_backup;

这应该是完全安全且非常快的。 唯一的问题是其他进程会看到表my_table消失几秒钟。 这可能会导致在各处的日志中显示错误。 所以这是一个安全的解决方案,但它“嘈杂”。

免责声明 :我不是MySQL专家,所以这些解决方案实际上可能很糟糕。 我能提供的唯一保证就是它对我来说很好。 如果有专家可以评论这些解决方案,我将不胜感激。

作为对您问题的回答:“我想重置所有数据,并在表格中保留最近30天。”

你可以创建一个事件。 检查https://dev.mysql.com/doc/refman/5.7/en/event-scheduler.html

例如:

CREATE EVENT DeleteExpiredLog
ON SCHEDULE EVERY 1 DAY
DO
DELETE FROM log WHERE date < DATE_SUB(NOW(), INTERVAL 30 DAY);

将在您的表中进行每日清理,保留最近30天的数据

您可以使用datapump简单地使用查询子句导出表,并使用table_exists_action = replace子句将其导回。 它会掉落并重新创建你的桌子,花费的时间更少。 请在实施前阅读相关内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM