环境信息
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
★ 登入容器 Bash: 然后,再次登入 Docker 容器的 Bash:
docker container exec -it 容器ID /bin/bash
因为我们的主机没有安装对应 MySQL 软件,所以登入容器执行。
1.逻辑全备份
cd /var/lib/mysql
mysqldump -uroot -p --add-drop-table --all-databases > all.sql
/var/lib/mysql
是 MySQL 当前的 datadir 数据文件路径。
-
--all-databases
备份所有的数据库。
-
--add-drop-table
在所有的 CREATE 语句前加上 DROP 语句。
-
那为什么要添加
-uroot -p
呢?是为了解决权限问题。
-
>
是输出重定向符号,表示将左边的内容输出到右边的文件中。
2.清除并重建数据文件
清除之前,建议停止当前 Docker 容器:
docker stop 容器ID
然后 cd 进入在Docker容器之/var/lib/mysql
在 宿主机的映射文件夹下:
比如我用 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 的大小变化,首先是重建前:
然后,是重建后:
3.恢复逻辑全备份
再次进入 Docker 中的 MySQL 容器 Bash 中:
cd /var/lib/mysql
mysql -uroot -p < all.sql
备份恢复之后,就可以删除 all.sql 了。