丟掉DDL,我用這招3分鐘清空 MySQL 9億記錄數據表 不停機不停服務,MYSQL能夠這樣修改億級數據表結構

摘要:最近因爲福建開機廣告生產環境的廣告日誌備份表主鍵(int類型)達到上限(21億多),不能再寫入數據,須要從新清空下該表並將主鍵重置,但因爲表裏有8億多記錄的數據量,使用重置命令及DDL命令執行地很是慢,因此採起刪除物理表結構文件的方式來進行快速清空表表數據!html

前言

一、本文介紹是在MySQL 5.5.29版本進行的操做,其餘的版本的沒有試過,有興趣的能夠本身嘗試去試下!mysql

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

1、數據背景及系統介紹

 

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

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億多),這使得最新的備份數據不能繼續寫入到該備份表了

因此,確認彙總表沒有數據缺失後,急需清空該備份表的數據,並重置下主鍵

 

2、爲何不用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、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能夠這樣修改億級數據表結構

相關文章
相關標籤/搜索