• Docker容器MySQL5.7系统表空间数据文件ibdata1


    环境信息

    • 主机:Ubuntu 20.04.2 LTS

    • Docker: 20.10.6

    • 镜像版本: mysql:5.7.19

    ibdata file

    在MySQL数据目录下,文件名称形如 ibdata1, ibdata2 之类的数据文件组成了 InnoDB 系统表空间。

    Reference click here

    ibdata 保存了什么?

    当你开启了 innodb_file_per_table (MySQL5.6之后默认开启),表被存储在他们自己的表空间里(数据和索引),但是系统表空间仍然在存储其它的 InnoDB 内部数据:

    • Data dictionary: 数据字典,也就是 InnoDB 表的元数据
    • 变更缓冲区
    • Double write buffer: 双写缓冲区
    • UNDO space: 撤销日志

    检查什么被存储到了 ibdata1 里了?

    本文主要介绍如何用 innochecksum 来查看什么被存储到 ibdata1 共享表空间的信息。

    坑1: page 0 invalid (fails old style checksum)

    我首先是参考 《MySQL的ibdata1详解》 提供的马克·卡拉汉制作的一个修改版 innochecksum ,它发布在这个漏洞报告里。我也确实下载、编译、执行了,但是现在这种方法已经行不通了。下面内容仅仅是记录一下思路:

    下载编译: 下载得到的 innochecksum.c.orig 是 C 语言源程序,需要 重命名 然后 编译一下

    mv innochecksum.c.orig innochecksum.c
    gcc innochecksum.c -o innochecksum
    

    这样就可以得到可执行文件 innochecksum 了。

    找到 ibdata1: 我们需要知道 Docker 容器挂载在当前主机的那个目录下,可以参考《查看Docker默认的volume地址》:

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


    这样我们知道主机上的文件位置 Source 与 Docker 容器的文件位置是对应的。因此,ibdata1 存在于 Source 所代表的本机地址中。所以我的 ibdata1 文件在主机上的地址就是
    /var/lib/docker/volumes/6cabb5980aa5e859e4fe389f8ed6dcfede8c126b696edb8e777addac800996e1/_data/ibdata1

    运行 innochecksum: 我们使用 innochecksum 工具来查看 ibdata1

    sudo innochecksum的文件地址 ibdata1在主机上的地址
    

    但是,使用这种方法会出现 page 0 invalid (fails old style checksum) 这个错误。

    ★ 为什么会出现这个错误呢?

    因为这个版本太老了,这个 BUG 的修复版本是 5.0.+,我们现在的 MySQL 已经是 5.7.+ ,出现不兼容的情况也很正常。你可以看一下对应的时间。

    坑2:Unable to lock file:: /var/lib/mysql/ibdata1

    在遇到“坑1”之后,我一度有点纠结该如何处理,我尝试从主机登录到 Docker 容器中:

    docker restart Docker容器ID
    docker container exec -it Docker容器ID /bin/bash
    

    查看 innochecksum 的版本:

    innochecksum --version
    


    我无意间发现 innochecksum 是可用的,应该是默认安装了。

    尝试使用 innochecksum 查看 ibdata1:

    innochecksum /var/lib/mysql/ibdata1
    

    但是,结果不尽如人意,出现了 Error: Unable to lock file:: /var/lib/mysql/ibdata1,解决方案是 停止当前的 mysql 服务

    停止 MySQL 服务:

    service mysql stop
    

    但是,停止后,会退出 Docker 容器的 Bash,回到主机的 Bash 中。

    解决方案

    所以,我想到有没有可能把 Docker 容器中的 innochecksum 拷贝到主机中,然后在主机执行 innochecksum?

    把docker容器内部的文件复制到本地:

    docker cp 容器id或名称:/path/filename /path/filename
    

    查看 innochecksum 在容器中的存储位置:

    which innochecksum 
    

    所以,最终把docker容器内部的文件复制到本地的命令是

    cd /var/lib/docker/volumes/6cabb5980aa5e859e4fe389f8ed6dcfede8c126b696edb8e777addac800996e1/_data/
    sudo docker cp 1626394823f9:/usr/bin/innochecksum ./
    

    现在 innochecksum 和 ibdata1 在同一个目录下了。

    使用 innochecksum 查看 Page 类型摘要:

    sudo ./innochecksum -S ibdata1
    

    除了 MySQL 正在运行时,Unable to lock file;假如没有权限,也可能导致 Unable to lock file。因此我加上了 sudo

    使用 innochecksum 查看 Page 总页数:

    sudo ./innochecksum -c ibdata1
    

    现在可以计算出 Undo log page 占 总页数的比例是 38808 / 41728 = 93%

    innochecksum的更多参数

    MySQL 5.7.19 附带的 innochecksum 支持以下参数 (通过 ./innochecksum 查看):

    参考文档

  • 相关阅读:
    Taxes
    Tennis Championship
    Urbanization
    字符串的匹配
    Alyona and a tree
    Alyona and mex
    Alyona and flowers
    Alyona and copybooks
    Subordinates
    线程的暂停、恢复和终止
  • 原文地址:https://www.cnblogs.com/kendoziyu/p/14809874.html
Copyright © 2020-2023  润新知