摘要:最近因爲福建開機廣告生產環境的廣告日誌備份表主鍵(int類型)達到上限(21億多),不能再寫入數據,須要從新清空下該表並將主鍵重置,但因爲表裏有8億多記錄的數據量,使用重置命令及DDL命令執行地很是慢,因此採起刪除物理表結構文件的方式來進行快速清空表表數據!html
一、本文介紹是在MySQL 5.5.29版本進行的操做,其餘的版本的沒有試過,有興趣的能夠本身嘗試去試下!mysql
二、本文介紹的是刪除frm和idb文件,同時不破壞原表結構的清空數據的方式!sql
爲更好說明問題,首先介紹下咱們系統的數據流轉的過程數據庫
step1:日誌入庫。API向機頂盒/EPG提供廣告接口,採集廣告請求日誌,當STB訪問EPG,EPG調用廣告請求接口獲取廣告策略,並寫入到報表數據庫的【廣告請求數據原始表t_ad_req_log】中;服務器
step2:存儲過程備份日誌表數據。因爲天天產生的廣告請求數據量有2000多萬,對於etl彙總時抽取有壓力,因此經過存儲過程將7天之前的數據備份到【廣告請求數據備份表t_ad_req_log_back】中,【廣告請求數據原始表t_ad_req_log】只保留7天內的數據,約8000萬~1億2千萬記錄左右;post
step3:etl抽取彙總。使用etl每小時抽取【廣告請求數據原始表t_ad_req_log】的上一時段的數據,抽取,分析,彙總寫入報表數據庫的【廣告/廣告位按時段彙總表】裏面;測試
step4:定時刪除備份日誌表數據。每隔一段時間檢查下數據etl彙總後的數據是否有問題,確認無誤數據沒問題後纔將【廣告請求數據備份表t_ad_req_log_back】清空,由於該表佔用空間實在太大了,不清空隔一段時間就會收到磁盤空間報警短信!url
本次就是有近2個月沒有清空數據,發現就有近9億條記錄(爲何這裏不用select count(*) 語句來查詢?是由於執行這樣一條語句10來分鐘都沒出結果,才用的explain來查看下錶中總數據記錄)spa
佔用磁盤空間也是高得嚇人,120G線程
固然不只僅是由於佔用磁盤太高,更重要的緣由是,該表的主鍵值達到int類型的上限值2147483646了(21億多),這使得最新的備份數據不能繼續寫入到該備份表了
因此,確認彙總表沒有數據缺失後,急需清空該備份表的數據,並重置下主鍵
經過上面確認【廣告請求數據備份表t_ad_req_log_back】表數據可刪後,當務之急就是要儘快清空數據,無疑最早想到的就是使用使用ALTER重置主鍵,執行命令:
ALTER TABLE t_ad_req_log AUTO_INCREMENT= 1;
開個小會,結果36分鐘過去沒有出現結果,尷尬了,執行線程查詢命令:
show processlist;
發現一直在「 copy to tmp table」,無奈,停下來試試執行drop命令:
DROP TABLE t_ad_req_log;
喝杯咖啡,執行了40分鐘還沒刪掉,快急出翔了。
什麼叫無能爲力?什麼叫難以啓齒的柔弱?大概就是MySQL DDL遇到9億級表結構的時候了吧!
因而不得已另選它法——刪除表文件ibd和frm方式!
固然,找到該表的文件,一鍵rm -rf 刪除仍是賊爽的,輕輕鬆鬆不用3分鐘。
不過由於不知道這麼刪會不會有什麼關聯影響,因而就先到測試服務器作了個測試,仍是遇到了些問題,記錄下步驟後,到現網刪除9億級記錄數據清空數據也是用了不到3分鐘?具體操做以下:
先在測試數據庫建立一個與現網【廣告請求數據備份表t_ad_req_log_back】同樣的表,而後將備份表的表文件t_ad_req_log_back.frm和t_ad_req_log_back.ibd拷貝到現網/home目錄下,這一步的操做主要是爲了後面解決建表時出現的「Table `t_ad_req_log_back` already exists」問題
切換到mysql的data目錄下,執行刪除命令:
rm -rf t_ad_req_log_back.*
再一看,磁盤空間並無釋放,仍是276G
因而使用lsof命令查看文件信息:
lsof -n|grep deleted
發現刪除程序還存活
繼續使用kill -9 27713命令該進程,磁盤空間獲得釋放
因爲表文件已經被刪掉,該表也就不存在,使用show命令查看也確實沒有發現這個表了
因而想繼續建表,發現報錯,報錯信息一直是「Table `t_ad_req_log_back` already exists」
Google了一下,才找到緣由,原來是:
因爲直接刪除了表的物理文件 但mysql的信息庫 information_schema 或 mysql 庫對該表的信息還存在,也就是說InnoDB格式的表索引都保存在ibdata1這個文件中,雖然物理文件被刪除,可是ibdata1中的索引沒有刪除,因此數據庫認爲該表已經存在,致使建立失敗,也就說直接rm -rf 表文件破壞了表結構。
難道這個表名就沒法再用了嗎?
固然能夠,j記得嗎?咱們最早作了個表結構備份,如今它派上用場了,將/home目錄下的兩個表文件t_ad_req_log_back.frm和t_ad_req_log_back.ibd拷貝到數據庫的data的目錄下,發現表存在了
執行desc命令發現又報錯「Table `t_ad_req_log_back` already exists」,這是怎回事呢?
改變用戶權限
chmod 660 t_ad_req_log_back.frm chown -R mysql:mysql t_ad_req_log_back.frm
而後再drop表, 刪除以後會發現該數據庫的data目錄下的物理文件夾中還存在t_ad_req_log_back.ibd文件, 刪除該文件,而後再次建表就ok了
至此,9億級表數據被清空了,同時表結構也沒有被破壞!
個人相關文章參考:不停機不停服務,MYSQL能夠這樣修改億級數據表結構