丟掉DDL,我用這招3分鍾清空 MySQL 9億記錄數據表


摘要:最近由於福建開機廣告生產環境的廣告日志備份表主鍵(int類型)達到上限(21億多),不能再寫入數據,需要重新清空下該表並將主鍵重置,但由於表里有8億多記錄的數據量,使用重置命令及DDL命令執行地非常慢,所以采取刪除物理表結構文件的方式來進行快速清空表表數據!

前言

1、本文介紹是在MySQL 5.5.29版本進行的操作,其他的版本的沒有試過,有興趣的可以自己嘗試去試下!

2、本文介紹的是刪除frm和idb文件,同時不破壞原表結構的清空數據的方式!

一、數據背景及系統介紹

 

為更好說明問題,首先介紹下我們系統的數據流轉的過程

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千萬記錄左右;

step3:etl抽取匯總。使用etl每小時抽取【廣告請求數據原始表t_ad_req_log】的上一時段的數據,抽取,分析,匯總寫入報表數據庫的【廣告/廣告位按時段匯總表】里面;

step4:定時刪除備份日志表數據。每隔一段時間檢查下數據etl匯總后的數據是否有問題,確認無誤數據沒問題后才將【廣告請求數據備份表t_ad_req_log_back】清空,因為該表占用空間實在太大了,不清空隔一段時間就會收到磁盤空間報警短信!

本次就是有近2個月沒有清空數據,發現就有近9億條記錄(為什么這里不用select count(*) 語句來查詢?是因為執行這樣一條語句10來分鍾都沒出結果,才用的explain來查看下表中總數據記錄)

占用磁盤空間也是高得嚇人,120G

 當然不僅僅是因為占用磁盤過高,更重要的原因是,該表的主鍵值達到int類型的上限值2147483646了(21億多),這使得最新的備份數據不能繼續寫入到該備份表了

所以,確認匯總表沒有數據缺失后,急需清空該備份表的數據,並重置下主鍵

 

二、為什么不用DDL

通過上面確認【廣告請求數據備份表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方式!

 

三、3分鍾刪除

當然,找到該表的文件,一鍵rm -rf 刪除還是賊爽的,輕輕松松不用3分鍾。

不過因為不知道這么刪會不會有什么關聯影響,於是就先到測試服務器做了個測試,還是遇到了些問題,記錄下步驟后,到現網刪除9億級記錄數據清空數據也是用了不到3分鍾?具體操作如下:

3.1 表結構備份

先在測試數據庫創建一個與現網【廣告請求數據備份表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”問題

3.2 刪掉現網表文件

切換到mysql的data目錄下,執行刪除命令:

rm -rf t_ad_req_log_back.*

再一看,磁盤空間並沒有釋放,還是276G

於是使用lsof命令查看文件信息:

lsof -n|grep deleted

發現刪除程序還存活

繼續使用kill -9 27713命令該進程,磁盤空間得到釋放

3.3 重新建表

由於表文件已經被刪掉,該表也就不存在,使用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可以這樣修改億級數據表結構


免責聲明!

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



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