2010-09-13 103 views
23

截斷 - >這將重置整個表,是否有一種方法通過truncate來重置特定的記錄/檢查條件。例如:截斷條件

例如:我想重置所有數據,並保留表格中的最後30天。

謝謝。

回答

38

不,TRUNCATE完全沒有。你可以做一個DELETE FROM <table> WHERE <conditions>但這失去了速度優勢TRUNCATE

+0

謝謝,假設條件下,如何保持過去10天的數據和以最佳方式刪除剩下的部分(表中有1000萬條記錄)。 – Sharpeye500 2010-09-13 22:20:13

+1

來自TRUNCATE的速度是因爲它沒有寫入日誌 – 2010-09-13 22:21:35

21

簡短的回答是沒有:MySQL不會把讓你一個WHERE條款添加到TRUNCATE聲明。這裏的MySQL's documentation關於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; 

不幸的是,這種解決方案是,如果其他進程有點不安全在表中同時插入記錄:

  • any re在步驟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專家,所以這些解決方案可能實際上是蹩腳的。我能提供的唯一保證是它們對我來說工作得很好。如果一些專家可以對這些解決方案發表評論,我將不勝感激。

+0

偉大的答案和良好的工作方式與限制。謝謝。 – 2016-01-25 22:39:30

0

您可以使用datapump簡單地使用查詢子句導出表並使用table_exists_action = replace子句將其導回。它會下降並重新創建你的桌子,並且花費更少的時間。實施前請閱讀。

0

作爲對您的問題的回覆: 「我想重置所有數據並保留表格中的最後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天的數據