MySQL刪除資料的簡單嘗試
在Oracle裡面對於資料清理,如果是非分割槽表,目前我經常的處理思路是下面三個。
第一種是中規中矩,做好備份,然後開始清理,當然這種情況只是說明資料清理的部分,不考慮高水位線的影響。可以使用shrink,move tablespace等來處理。
補充一句,其實這個dump這是一種形式,可以採用各種形式的資料匯出格式,比如sqlldr適用的csv,比如外部表,比如expdp,exp的匯出二進位制dump等。
第二種思路是邏輯備份,就是把表採用ctas的方式備份一份。然後對原來的表進行資料清理。這種情況下,佔用的是資料庫內的資料空間。
第三種思路是迂迴戰術,就是把原表改一個別名,然後新建一個同名的表(表裡沒有資料,只有表結構),然後把需要的增量資料插入到新表中.
這種思路在MySQL裡面也是類似,不過值得一提的是MySQL的rename著實比較牛,因為MySQL中的database和Oracle中的user的含義有些類似,MySQL裡面很輕鬆的使用rename操作把一個資料庫A中的表TEST很輕鬆的rename倒資料庫B裡面。
最近開發的同事反饋有一個業務的查詢著實太慢,結果分析下來發現一種改善思路就是刪除舊資料。因為確實很長時間沒有清理了。
簡單和開發溝通了一下,其實有幾種思路可以走,不過就看具體的需求了。開發說保留近半年的資料,提供的清理sql如下。
半年以前的資料有大概300萬。
mysql> select count(*)from recharge where occur_time<'2015-07-01 00:00:00';
+----------+
| count(*) |
+----------+
| 2945974 |
+----------+
1 row in set (1 min 20.13 sec)
需要保留的資料有50多萬。
mysql> select count(*)from fact_recharge where occur_time > '2015-07-01 00:00:00';
+----------+
| count(*) |
+----------+
| 550422 |
+----------+
1 row in set (1 min 25.46 sec)
所以按照這個比例,其實選用第三種方法看起來要好些,不過限於本地的空間,而且開發說這個表刪除的舊資料需要檢視,恢復的可能性極小,所以我就一次弄乾淨點,直接物理備份出來清理,採用了第一種方式。
簡單評估之後就開始操作。
先開始做備份。
mysqldump --default-character-set=UTF8 --single-transaction -q -R --triggers --tables test_ad xxxx_regok |gzip > /data2/dba/databak/tab_bak/full_20150203_us_test_ad_xxxx_regok.sql.gz
然後就按照常規思路開始刪除,不過看起來很簡單的刪除竟然還報錯了。
mysql> delete from recharge where occur_time<'2015-07-01 00:00:00';
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
這個錯誤看來和binlog的cache size有很大的關係,目前的binlog設定如下
mysql> show variables like '%binlog%';
+-----------------------------------------+----------------------+
| Variable_name | Value |
+-----------------------------------------+----------------------+
| binlog_cache_size | 4194304 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_format | ROW |
| binlog_stmt_cache_size | 32768 |
| innodb_locks_unsafe_for_binlog | OFF |
| max_binlog_cache_size | 536870912 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| sync_binlog | 0 |
+-----------------------------------------+----------------------+
9 rows in set (0.00 sec)
而且比較糾結的是這個環境是採用了級聯複製,動一處需要聯動修改多處。目前的binlog cache size是500M左右。刪除的資料肯定要大於這個cache_size.
所以這個時候還得使用另外一種迂迴戰術,那就是分批刪了。可以考慮使用datediff來作為一個基準刪除。
現在距離2015年7月1日有217天的時間差,那麼我們就按照這個時間差來做點文章,分批刪除。
mysql> select datediff(now(),'2015-07-01 00:00:00') ;
+---------------------------------------+
| datediff(now(),'2015-07-01 00:00:00') |
+---------------------------------------+
| 217 |
+---------------------------------------+
1 row in set (0.00 sec)
當前時間為:
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2016-02-03 00:01:28 |
+---------------------+
1 row in set (0.00 sec)
當然老是喜歡用oracle的語句檢驗一下。
SQL> SQL> select sysdate-217 from dual;
SYSDATE-217
-------------------
2015-07-01 16:02:03
好了,開始刪除資料,可以使用下面的語句,不過還需要改進一下。
delete from fact_recharge where datediff(now(),occur_time) >217
那麼刪除的邊界值怎麼確定呢。
mysql> select max(datediff(now(),occur_time)) from fact_recharge where datediff(now(),occur_time) >217 ;
+---------------------------------+
| max(datediff(now(),occur_time)) |
+---------------------------------+
| 16835 |
+---------------------------------+
1 row in set (3.69 sec)
這個結果讓我有些無語,應該是裡面有一些資料不光舊,而且還有問題。
SQL>select sysdate-16835 from dual
SYSDATE-16835
-------------------
1969-12-31 16:04:59
需要調節刪除的跨度。
mysql> delete from recharge where datediff(now(),occur_time)>218 and datediff(now(),occur_time) < 800;
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
mysql> delete from recharge where datediff(now(),occur_time)>218 and datediff(now(),occur_time) < 300;
Query OK, 310067 rows affected (36.78 sec)
mysql> delete from recharge where datediff(now(),occur_time)>300 and datediff(now(),occur_time) < 500;
Query OK, 1065870 rows affected (1 min 50.08 sec)
mysql> delete from recharge where datediff(now(),occur_time)>500 and datediff(now(),occur_time) <700;
Query OK, 1021640 rows affected (1 min 59.31 sec)
mysql> delete from recharge where datediff(now(),occur_time)>700 and datediff(now(),occur_time) < 1000;
Query OK, 505048 rows affected (2 min 29.91 sec)
資料已經大體刪除,我們可以使用修改儲存引擎達到釋放碎片的目的了。
mysql> alter table recharge engine=InnoDB;
Query OK, 594253 rows affected (4 min 19.94 sec)
Records: 594253 Duplicates: 0 Warnings: 0
修改之後,刪除了大概2G左右的空間。
# ll recharge*|du -sh .
33G .
# ll recharge*|du -sh .
31G .
當然剛剛的刪除還做了一些保留,為了對比,再次嘗試,刪除的工作就很快了。
mysql> delete from recharge where datediff(now(),occur_time)>1000;
Query OK, 25712 rows affected (2.03 sec)
mysql> delete from recharge where datediff(now(),occur_time)>218;
Query OK, 14400 rows affected (1.05 sec)
所以透過這個小的嘗試也可以看出來其實有些處理思路還是相通的,但是技術細節上還有很多需要繼續琢磨的地方。
第一種是中規中矩,做好備份,然後開始清理,當然這種情況只是說明資料清理的部分,不考慮高水位線的影響。可以使用shrink,move tablespace等來處理。
補充一句,其實這個dump這是一種形式,可以採用各種形式的資料匯出格式,比如sqlldr適用的csv,比如外部表,比如expdp,exp的匯出二進位制dump等。
第二種思路是邏輯備份,就是把表採用ctas的方式備份一份。然後對原來的表進行資料清理。這種情況下,佔用的是資料庫內的資料空間。
第三種思路是迂迴戰術,就是把原表改一個別名,然後新建一個同名的表(表裡沒有資料,只有表結構),然後把需要的增量資料插入到新表中.
這種思路在MySQL裡面也是類似,不過值得一提的是MySQL的rename著實比較牛,因為MySQL中的database和Oracle中的user的含義有些類似,MySQL裡面很輕鬆的使用rename操作把一個資料庫A中的表TEST很輕鬆的rename倒資料庫B裡面。
最近開發的同事反饋有一個業務的查詢著實太慢,結果分析下來發現一種改善思路就是刪除舊資料。因為確實很長時間沒有清理了。
簡單和開發溝通了一下,其實有幾種思路可以走,不過就看具體的需求了。開發說保留近半年的資料,提供的清理sql如下。
半年以前的資料有大概300萬。
mysql> select count(*)from recharge where occur_time<'2015-07-01 00:00:00';
+----------+
| count(*) |
+----------+
| 2945974 |
+----------+
1 row in set (1 min 20.13 sec)
需要保留的資料有50多萬。
mysql> select count(*)from fact_recharge where occur_time > '2015-07-01 00:00:00';
+----------+
| count(*) |
+----------+
| 550422 |
+----------+
1 row in set (1 min 25.46 sec)
所以按照這個比例,其實選用第三種方法看起來要好些,不過限於本地的空間,而且開發說這個表刪除的舊資料需要檢視,恢復的可能性極小,所以我就一次弄乾淨點,直接物理備份出來清理,採用了第一種方式。
簡單評估之後就開始操作。
先開始做備份。
mysqldump --default-character-set=UTF8 --single-transaction -q -R --triggers --tables test_ad xxxx_regok |gzip > /data2/dba/databak/tab_bak/full_20150203_us_test_ad_xxxx_regok.sql.gz
然後就按照常規思路開始刪除,不過看起來很簡單的刪除竟然還報錯了。
mysql> delete from recharge where occur_time<'2015-07-01 00:00:00';
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
這個錯誤看來和binlog的cache size有很大的關係,目前的binlog設定如下
mysql> show variables like '%binlog%';
+-----------------------------------------+----------------------+
| Variable_name | Value |
+-----------------------------------------+----------------------+
| binlog_cache_size | 4194304 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_format | ROW |
| binlog_stmt_cache_size | 32768 |
| innodb_locks_unsafe_for_binlog | OFF |
| max_binlog_cache_size | 536870912 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| sync_binlog | 0 |
+-----------------------------------------+----------------------+
9 rows in set (0.00 sec)
而且比較糾結的是這個環境是採用了級聯複製,動一處需要聯動修改多處。目前的binlog cache size是500M左右。刪除的資料肯定要大於這個cache_size.
所以這個時候還得使用另外一種迂迴戰術,那就是分批刪了。可以考慮使用datediff來作為一個基準刪除。
現在距離2015年7月1日有217天的時間差,那麼我們就按照這個時間差來做點文章,分批刪除。
mysql> select datediff(now(),'2015-07-01 00:00:00') ;
+---------------------------------------+
| datediff(now(),'2015-07-01 00:00:00') |
+---------------------------------------+
| 217 |
+---------------------------------------+
1 row in set (0.00 sec)
當前時間為:
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2016-02-03 00:01:28 |
+---------------------+
1 row in set (0.00 sec)
當然老是喜歡用oracle的語句檢驗一下。
SQL> SQL> select sysdate-217 from dual;
SYSDATE-217
-------------------
2015-07-01 16:02:03
好了,開始刪除資料,可以使用下面的語句,不過還需要改進一下。
delete from fact_recharge where datediff(now(),occur_time) >217
那麼刪除的邊界值怎麼確定呢。
mysql> select max(datediff(now(),occur_time)) from fact_recharge where datediff(now(),occur_time) >217 ;
+---------------------------------+
| max(datediff(now(),occur_time)) |
+---------------------------------+
| 16835 |
+---------------------------------+
1 row in set (3.69 sec)
這個結果讓我有些無語,應該是裡面有一些資料不光舊,而且還有問題。
SQL>select sysdate-16835 from dual
SYSDATE-16835
-------------------
1969-12-31 16:04:59
需要調節刪除的跨度。
mysql> delete from recharge where datediff(now(),occur_time)>218 and datediff(now(),occur_time) < 800;
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
mysql> delete from recharge where datediff(now(),occur_time)>218 and datediff(now(),occur_time) < 300;
Query OK, 310067 rows affected (36.78 sec)
mysql> delete from recharge where datediff(now(),occur_time)>300 and datediff(now(),occur_time) < 500;
Query OK, 1065870 rows affected (1 min 50.08 sec)
mysql> delete from recharge where datediff(now(),occur_time)>500 and datediff(now(),occur_time) <700;
Query OK, 1021640 rows affected (1 min 59.31 sec)
mysql> delete from recharge where datediff(now(),occur_time)>700 and datediff(now(),occur_time) < 1000;
Query OK, 505048 rows affected (2 min 29.91 sec)
資料已經大體刪除,我們可以使用修改儲存引擎達到釋放碎片的目的了。
mysql> alter table recharge engine=InnoDB;
Query OK, 594253 rows affected (4 min 19.94 sec)
Records: 594253 Duplicates: 0 Warnings: 0
修改之後,刪除了大概2G左右的空間。
# ll recharge*|du -sh .
33G .
# ll recharge*|du -sh .
31G .
當然剛剛的刪除還做了一些保留,為了對比,再次嘗試,刪除的工作就很快了。
mysql> delete from recharge where datediff(now(),occur_time)>1000;
Query OK, 25712 rows affected (2.03 sec)
mysql> delete from recharge where datediff(now(),occur_time)>218;
Query OK, 14400 rows affected (1.05 sec)
所以透過這個小的嘗試也可以看出來其實有些處理思路還是相通的,但是技術細節上還有很多需要繼續琢磨的地方。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-2038984/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 簡單介紹mysql如何刪除資料表和關聯的資料表刪除詳情MySql
- MySQL控制程式碼恢復的簡單嘗試MySql
- MySQL刪除資料表MySql
- MySQL:簡單記錄刪除binary log的介面MySql
- MySQL刪除重複資料MySql
- MySQL 5.5複製升級到5.7的一點簡單嘗試MySql
- 嘗試讓查詢更簡單
- MySQL(四) 資料表的插入、更新、刪除資料MySql
- [MYSQL -20]更新和刪除資料MySql
- [MYSQL] 資料庫建立與刪除MySql資料庫
- mysql 刪除表中重複的資料MySql
- go1.18泛型的簡單嘗試Go泛型
- whk我【資料刪除】你個【資料刪除】的
- MySQL超大表刪除資料過程MySql
- MySQL 中刪除的資料都去哪兒了?MySql
- 【MySQL】刪除大量資料的具體實現MySql
- 如何刪除資料庫下的所有表(mysql)資料庫MySql
- 【開源之路】溫蒂、一次簡單的嘗試
- Unity嘗試實現簡單的行為樹-01Unity
- MySQL 批量更新、刪除資料shell指令碼MySql指令碼
- mysql資料庫誤刪除操作說明MySql資料庫
- 刪除資料
- MySQL防止delete命令刪除資料的兩種方法MySqldelete
- Mysql資料庫值的新增、修改、刪除及清空MySql資料庫
- React實現表單資料的新增與刪除React
- MySQL之資料的簡單查詢MySql
- mysql資料庫誤刪除後的資料恢復操作說明MySql資料庫資料恢復
- MySQL 資料庫誤刪除後的資料恢復操作說明MySql資料庫資料恢復
- 【MySQL】批量刪除mysql中資料庫中的表MySql資料庫
- Mysql資料庫delete刪除後資料恢復報告MySql資料庫delete資料恢復
- MySQL資料庫表誤刪除恢復(一)MySql資料庫
- 6、MySQL刪除資料庫(DROP DATABASE語句)MySql資料庫Database
- 【常用方法推薦】如何刪除MySQL的重複資料?MySql
- ASM磁碟簡單維護,新增,刪除ASM
- mysql簡單效能測試MySql
- indexedDB 刪除資料Index
- Solr刪除資料Solr
- 刪除elasticsearch資料Elasticsearch