Truncate with condition
截断->这将重置整个表,是否可以通过截断来重置特定的记录/检查条件。
例如:我想重置所有数据,并在表格中保留过去30天。
谢谢。
不,
1 2 3 | 1. LOCK TABLE my_table WRITE; 2. DELETE FROM my_table WHERE my_date<DATE_SUB(NOW(), INTERVAL 1 MONTH); 3. UNLOCK TABLES; |
不幸的是,如果您的表很大,这将非常慢...并且由于您正在考虑使用
因此,这是使用
使用
1 2 3 4 5 6 7 | 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发生冲突(请注意,AUTO-INCREMENT 计数器将在第4步之后恢复为正确的值) 。
不幸的是,不可能锁定表并截断它。但是我们可以(以某种方式)使用
使用
1 2 3 4 5 6 7 8 9 | 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; |
这应该是完全安全且相当快的。唯一的问题是其他进程将看到表
免责声明:我不是MySQL专家,所以这些解决方案实际上可能很糟糕。我能提供的唯一保证是它们对我来说很好。如果某些专家可以对这些解决方案发表评论,我将不胜感激。
回答您的问题:
"我想重置所有数据并在表格中保留过去30天。"
您可以创建一个事件。检查https://dev.mysql.com/doc/refman/5.7/zh-CN/event-scheduler.html
例如:
1 2 3 4 | 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子句将其导入回来。它会删除并重新创建您的表,并且花费的时间更少。在实施之前,请先阅读有关内容。