大量刪除MySQL中的數據


出現的背景:

公司做了一個redis相關的項目,其中mysql存儲了很多統計數據。比如客戶端上報的數據,redis實例的數據,應用的數據,機器的數據等。每天都在上報,采集,由於沒有定期刪除,數據大量累積。大概有一年左右的數據,一個表的數據已經達到億級別的。這樣算下來,一個表的數據至少是幾十GB了。因此需要刪除過期的數據,暫時保留近三個月的統計數據。

解決方案:

基本每個表都有個字段叫create_time或者collect_time的字段,只要刪除這個字段三個月之前的數據就ok了

delete from table_name where create_time < '2017-04-06'

只要執行這句SQL應該就可以了

遇到的問題:

The total number of locks exceeds the lock table size in MySQL

因為需要刪除的數據太大,mysql給的buffer好像只有8MB左右(網上搜到的)

后面找到DBA幫忙看,問這個表建了索引沒有

show index from table_name

通過查看索引,我們在create_time和collect_time上是建了索引的,索引類型是BTree,ASC。這里我們用的Mysql引擎是InnoDb

delete from table_name where create_time < '2017-07-06'  order by create_time asc limit 10000

接着,我想用order by + limit實現刪除,還是出現了上面的錯誤

后面DBA提示我說,為啥不用ID刪除,說按id刪除,速度和按索引列刪除,不是一個數量級的

接着我想到了拆分一下。

最終解決方案:

找出符合條件的create_time和collect_time的最大ID

select max(id) from table_name where create_time < '2017-04-06'

這里千萬左右的數據大概需要10多秒

接着按id刪除,一次刪除10k,循環刪除

delete from table_name where id < maxId limit 10000

直到把過期的時間刪除完成

這里我沒有msyql服務器的權限,通過java客戶端連接刪除,使用的spring jdbcTemplate這個接口

另外,這里一次刪除10k還有個原因是,事務太大,影響其他服務的運行

 

還用到的技術,就是使用線程池來執行sql刪除,實現異步刪除。和同事吃飯的時候,同事也提供了一個解決方案,每次刪一秒的數據,這樣一次次的刪。看了一下數據,一秒的數據基本在幾十萬,左右,這樣不太好控制數據量大小。還是通過主鍵id + limit 10k這里穩妥一點。

還有一點就是,為了怕壓到mysql服務器,這里線程池刪除的時候回sleep(1000),阻塞1s再刪除,減輕mysql服務器的壓力

 

今天搞了一下數據刪除這一點東西,感覺mysql水很深,比如一個select count(*)的執行過程,select from table_name order by id limit 的過程,索引,各種連接,引擎的工作原理。走的時候還有點沒有調完,明天應該可以搞定這些了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM