• 记一次docker的mysql损坏修复经历


    一、问题描述

    近日由于市政电路整改,机房被迫断电。其中有一台ubuntu主机没有手工关机,重新送电后ubuntu主机重启成功。但在ubuntu宿主上用docker安装的mysql动无法启动。

    (1)尝试进入docker命令行:

    $ docker exec -it mysql57 env LANG=C.UTF-8 /bin/bash
    得到

    Error response from daemon: Container 40580276ee2f0bf30e59d9ff670977b27856a36ed10b788e3a3fce8f17d7849b is not running
    
    • 1

    (2)面向百度得到docker logs {容器}的建议。结果:

    $ docker logs mysql57

    Initializing database
    Database initialized
    MySQL init process in progress...
    Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
    Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
    Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
    /entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
    MySQL init process done. Ready for start up.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (3) 请教GPT后得到删除并重建的建议。

    二、使用docker部署mysql的一些思考

    对于数据库,最重要的就是数据的安全性要得到保证。
    所以必须要确保即使docker容器损坏后,仍然能够拿到mysql存储的数据文件。
    因此在初始化docker容器时,只要将数据目录挂载到宿主机上的自定义目录即可。

    三、实施重建

    这里假设我的宿主用户名为study

    1.删除旧的已损坏的mysql实例

    docker stop mysql57
    docker rm mysql57
    
    • 1
    • 2

    2.创建在宿主机上创建mysql数据相关目录

    备份损坏前的数据文件

    #进入数据目录的父目录
    /home/study/database
    #备份文件夹
    sudo zip -r MYSQL_DATA.zip MYSQL_DATA
    #删除原有的DATA目录
    sudo rm -rf MYSQL_DATA
    sudo mkdir MYSQL_DATA
    sudo chmod -R 755 /home/study/database
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里我在宿主上创建了一个文件夹/home/study/database/MYSQL_DATA作为mysql的数据目录。因此这里要先备份它。

    这是我初次安装时创建的一些目录和文件 :

    #日志目录
    sudo mkdir -p "/home/study/database/logs"
    #数据目录
    sudo mkdir -p "/home/study/database/MYSQL_DATA"
    #配置目录 
    sudo mkdir -p "/home/study/database/conf"
    #创建文件
    sudo touch /home/study/database/logs/mysqld-error.log
    sudo touch  /home/study/database/conf/mysqld.pid
    3.重建实例
    sudo docker run --name mysql57 -p 3308:3306 -e MYSQL_ROOT_PASSWORD=studyDB -d  \ 
    --mount type=bind,src=/home/study/database/logs/mysqld-error.log,dst=/var/log/mysqld.log \  
    --mount type=bind,src=/home/study/database/MySQL_DATA,dst=/var/lib/mysql mysql/mysql-server:5.7.18 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    命令解读:

    sudo 以管理员身份执行
    docker run 是docker容器初始化的命令。
    
    --name mysql57 容器取名为mysql57后期维护用这个名字,相当于给容器ID取个别名。
    -p 3308:3306 这里有两个端口3306是容器中mysql进程监听的端口,3308是通过宿主IP来访问数据库时宿主机的端口。相当于将容器中的3306映射到宿主机的3308上。
    
    -e MYSQL_ROOT_PASSWORD=studyDB 指定root帐号的密码
    
    -d 选项是 "detached""daemon" 的缩写,它的作用是将容器在后台运行,而不是占用当前终端会话。具体来说,它指示Docker将容器作为后台进程启动,然后返回到命令行终端,允许您继续使用该终端而不会阻止在容器上运行的应用程序。
    
    \ 用于将一条很长的命令分成多行来书写。相当于行与行之间的连接符。
    
    --mount type=bind,src=/home/study/database/logs/mysqld-error.log,dst=/var/log/mysqld.log
      这一句--mount是挂载宿主文件路径,src是宿主路径,dst是容器中的命令
      相当于在docker容器中创建了一个文件软链接,指定此参数后,在容器中往路径/var/log/mysqld.log中写入内容时,实际内容会被写入到宿主的/home/study/database/logs/mysqld-error.log这个文件。
    
    --mount type=bind,src=/home/study/database/MySQL_DATA,dst=/var/lib/mysql 
      这一句--mount是挂载宿主文件目录路径,src是宿主路径,dst是容器中的命令
      相当于在docker容器中创建了一个文件软链接,指定此参数后,在容器中往目录/var/lib/mysql下写入内容时,实际内容会被写入到宿主的/home/study/database/MySQL_DATA目录下。
    
    mysql/mysql-server:5.7.18  这是docker pull拉取的镜像名称,意思是以它为模板运行实例。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    以上执行成功后,启动mysql容器:

    #启动容器
    docker start mysql57
    #修改容器重启策略,让它随宿主机开机自启
    docker update --restart=always mysql57
    
    • 1
    • 2
    • 3
    • 4

    进入容器并设置中文支持

    #第一步:进入时加环境变量参数env LANG=C.UTF-8 
    docker exec -it mysql57 env LANG=C.UTF-8 /bin/bash
    #第二步:安装vi程序
    yum install vi
    #第三步:vi /etc/profile  文件尾插入
    LANG=en_ZW.utf8
    #第四步:配置生效
    source /etc/profile
    #验证mysql登录
    mysql -uroot -pstudyDB --default-character-set=utf8
    #退出mysql命令行
    quit
    
    #修改mysql配置
    vim /etc/my.cnf  添加下面的sql_mode和lower_case_table_names
    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    #解析SQL语句时,忽略库表名称大小写
    lower_case_table_names=1
    #时间为东八区
    default-time_zone = "+8:00"
    
    #退出mysql容器
    exit
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    4.还原数据

    #停止mysql
    sudo docker stop mysql57
    #进入备份所在目录
    cd /home/study/database
    #直接解压覆盖所有文件
    sudo unzip MYSQL_DATA.zip
    #重启mysql
    sudo docker start mysql57
    #进入容器命令行
    docker exec -it mysql57 env LANG=C.UTF-8 /bin/bash
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    四、总结

    这是在生产环境使用docker后第一次遇到容器损坏的情况。
    本次事故能够得到解决主要得益于新技术应用之前做好了风险把控,将Mysql的数据目录映射到宿主的文件夹中。否则一旦容器损坏,后果难以设想。

  • 相关阅读:
    不清楚Word如何批量转PDF?快来跟我学这两个妙招
    Git与SSH
    学会解决问题的方法
    第5 章 项目集管理 第6 章 项目组合管理
    14 C++设计模式之策略(Strategy)模式
    完美十进制数——去年天梯校赛
    “萌系小家电”顶流的小熊电器,如何创造全域增长?
    一例疑似MMCore下载器分析
    hive数据库delete删除部分数据/删除分区内的数据
    BP绁炵粡缃戠粶浠跨湡,bp绁炵粡缃戠粶妯″瀷
  • 原文地址:https://blog.csdn.net/hansonjan/article/details/133759648