天天看點

Docker容器MySQL5.7的ibdata1過大問題解決

環境資訊

1、主控端:Ubuntu 20.04.2 LTS

2、Docker: 20.10.6

3、鏡像版本: mysql:5.7.19

簡述

上一節,在《Docker容器MySQL5.7系統表空間資料檔案ibdata1》 中,分析如何使用 innochecksum 工具來分析了什麼被存儲到了 ibdata1 裡。我們發現 Undo log page 占據了 ibdata1 中 93% 的空間。

那麼,有什麼辦法回收已使用的空間嗎?

沒有,目前還沒有一個容易并且快速的方法。InnoDB 表空間從不收縮...

當你删除一些行,這個頁被标為已删除稍後重用,但是這個空間從不會被回收。唯一的方法是使用新的 ibdata1 啟動資料庫。要做這個你應該需要使用 mysqldump 做一個邏輯全備份,然後停止 MySQL 并删除所有資料庫、

ib_logfile*

ibdata*

檔案。當你再啟動 MySQL 的時候将會建立一個新的共享表空間。然後恢複邏輯備份。

不過 Docker 的話,還是删除整個檔案夾再重建一個新的空檔案夾更友善,否則重新開機容器時,會因為 datadir 不為空,導緻無法正常初始化而失敗。

0.前置準備

★ 重新開機服務: 首先,我們把 Docker 容器的 MySQL 服務停掉了,現在我們先重新拉起:

docker ps -a
docker restart 容器ID
           
Docker容器MySQL5.7的ibdata1過大問題解決

★ 登入容器 Bash: 然後,再次登入 Docker 容器的 Bash:

docker container exec -it 容器ID /bin/bash
           
Docker容器MySQL5.7的ibdata1過大問題解決

因為我們的主機沒有安裝對應 MySQL 軟體,是以登入容器執行。

1.邏輯全備份

cd /var/lib/mysql
mysqldump -uroot -p --add-drop-table --all-databases > all.sql
           

/var/lib/mysql

是 MySQL 目前的 datadir 資料檔案路徑。
  • --all-databases

    備份所有的資料庫。
    Docker容器MySQL5.7的ibdata1過大問題解決
  • --add-drop-table

    在所有的 CREATE 語句前加上 DROP 語句。
    Docker容器MySQL5.7的ibdata1過大問題解決
  • 那為什麼要添加

    -uroot -p

    呢?是為了解決權限問題。
    Docker容器MySQL5.7的ibdata1過大問題解決
  • >

    是輸出重定向符号,表示将左邊的内容輸出到右邊的檔案中。

2.清除并重建資料檔案

清除之前,建議停止目前 Docker 容器:

docker stop 容器ID
           

然後 cd 進入在Docker容器之

/var/lib/mysql

在 主控端的映射檔案夾下:

Docker容器MySQL5.7的ibdata1過大問題解決

比如我用

docker container inspect

檢視到我的主控端映射目錄是

/var/lib/docker/volumes/6cabb5980aa5e859e4fe389f8ed6dcfede8c126b696edb8e777addac800996e1/_data

docker container inspect 容器ID | grep Mounts -A 20
           

★ 先把 all.sql 轉移走

cd /var/lib/docker/volumes/6cabb5980aa5e859e4fe389f8ed6dcfede8c126b696edb8e777addac800996e1/_data
mv all.sql ~/
           

★ 移除 _data 檔案夾

cd /var/lib/docker/volumes/6cabb5980aa5e859e4fe389f8ed6dcfede8c126b696edb8e777addac800996e1/
rm -rf _data/
mkdir _data
           

★ 再把 all.sql 放回映射的資料檔案夾

cd /var/lib/docker/volumes/6cabb5980aa5e859e4fe389f8ed6dcfede8c126b696edb8e777addac800996e1/_data
mv ~/all.sql ./
           

然後,重新開機 Docker 服務。重複 0.前置準備 中的操作,當你再啟動 MySQL 的時候将會建立一個新的共享表空間。

我們可以對比一下 ibdata1 的大小變化,首先是重建前:

Docker容器MySQL5.7的ibdata1過大問題解決

然後,是重建後:

Docker容器MySQL5.7的ibdata1過大問題解決

3.恢複邏輯全備份

再次進入 Docker 中的 MySQL 容器 Bash 中:

cd /var/lib/mysql
mysql -uroot -p < all.sql
           

備份恢複之後,就可以删除 all.sql 了。

參考文檔

1、《解決ibdata1資料庫過大的問題》

2、《MySQL的ibdata1詳解》

繼續閱讀