正文前先來一波福利推薦:
福利一:
百萬年薪架構師視頻,該視頻可以學到很多東西,是本人花錢買的VIP課程,學習消化了一年,為了支持一下女朋友公眾號也方便大家學習,共享給大家。
福利二:
畢業答辯以及工作上各種答辯,平時積累了不少精品PPT,現在共享給大家,大大小小加起來有幾千套,總有適合你的一款,很多是網上是下載不到。
獲取方式:
微信關注 精品3分鍾 ,id為 jingpin3mins,關注后回復 百萬年薪架構師 ,精品收藏PPT 獲取雲盤鏈接,謝謝大家支持!

-----------------------正文開始---------------------------
最新項目一直出現線上問題,定位原因看到是由於表數據過大導致的,現在有個登錄表,登錄游戲玩家每次登錄的信息,久而久之,這幾個表的數據量達到了兩億多條。每天都在上報,采集,由於沒有定期刪除,數據大量累積。大概有一年左右的數據,一個表的數據已經達到億級別的。這樣算下來,一個表的數據至少是幾十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 的過程,索引,各種連接,引擎的工作原理。走的時候還有點沒有調完,明天應該可以搞定這些了。
