砸你家玻璃 發表於 2026-1-9 08:53:58

Docker下Mysql8数据备份与恢复实现

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1 创建Mysql容器</a></li><li><a href="#_label1">2 连接Mysql</a></li><li><a href="#_label2">3 Binlog检查</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">3.1 检查是否开启</a></li><li><a href="#_lab2_2_1">3.2 mysql 5.7</a></li><li><a href="#_lab2_2_2">3.3 mysql8</a></li></ul><li><a href="#_label3">4 备份数据库</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_3">4.1 容器里执行备份</a></li><li><a href="#_lab2_3_4">4.2 宿主机执行备份</a></li><li><a href="#_lab2_3_5">4.3 参数说明</a></li></ul><li><a href="#_label4">5 定时备份</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">6 恢复数据</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">7 注意事项</a></li><ul class="second_class_ul"><li><a href="#_lab2_6_6">7.1 定时备份,出现the input device is not a TTY</a></li><li><a href="#_lab2_6_7">7.2 提示</a></li></ul><li><a href="#_label7">​总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>1 创建Mysql容器</h2>
<ul><li>格式</li></ul>
<div class="jb51code"><pre class="brush:bash;">docker run -d
--name=容器名称
-p 宿主端口号:3306
-e MYSQL_ROOT_PASSWORD=mysql密码
-e MYSQL_PASSWORD=mysql密码
-e TZ=Asia/Shanghai
-v 宿主目录-数据:/var/lib/mysql
-v 宿主目录-备份数据:/backup
--restart always
mysql:版本号</pre></div>
<ul><li>示例</li></ul>
<div class="jb51code"><pre class="brush:bash;">docker run -d --name=mysql-8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_PASSWORD=123456 -e TZ=Asia/Shanghai -v /workspace/mysql-8:/var/lib/mysql -v /workspace/mysql-8-backup:/backup --restart always mysql:8.0</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>2 连接Mysql</h2>
<ul><li>Navicat</li></ul>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010908505648.png" /></p>
<ul><li>创建SQL</li></ul>
<div class="jb51code"><pre class="brush:sql;">-- 删除数据库
DROP DATABASE IF EXISTS `test`;
-- 创建数据库
CREATE DATABASE IF NOT EXISTS `test`;
-- 进入数据库
use `test`;
-- 创建表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- 插入数据
INSERT INTO `student` (`id`, `name`,`age`) VALUES (1, '小红', '20');
INSERT INTO `student` (`id`, `name`,`age`) VALUES (2, '小明', '21');</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3 Binlog检查</h2>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>3.1 检查是否开启</h3>
<div class="jb51code"><pre class="brush:sql;">SHOW VARIABLES like 'log_bin';</pre></div>
<ul><li>ON : 开启</li><li>OFF : 关闭</li></ul>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>3.2 mysql 5.7</h3>
<ul><li>找到 <code>my.cnf</code></li></ul>
<div class="jb51code"><pre class="brush:bash;">find / -name my.cnf </pre></div>
<ul><li>docker 位置: <code>/etc/my.cnf</code></li><li>开启</li></ul>
<div class="jb51code"><pre class="brush:bash;">
log_bin = mysql-bin
server_id = 1   # 设置MySQL实例的唯一ID,如果有多个MySQL实例,每个实例的ID必须不同</pre></div>
<p class="maodian"><a name="_lab2_2_2"></a></p><h3>3.3 mysql8</h3>
<ul><li>默认开启</li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>4 备份数据库</h2>
<p class="maodian"><a name="_lab2_3_3"></a></p><h3>4.1 容器里执行备份</h3>
<ul><li>进入容器</li></ul>
<div class="jb51code"><pre class="brush:bash;">docker exec -ti mysql-8 /bin/bash</pre></div>
<ul><li>在容器内创建备份目录</li><li>前面创建容器时已创建,没有则执行下面</li></ul>
<div class="jb51code"><pre class="brush:bash;">mkdir /backup</pre></div>
<ul><li>全量备份SQL</li></ul>
<div class="jb51code"><pre class="brush:bash;">mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot -p123456 test &gt; /backup/test_20240713.sql</pre></div>
<p class="maodian"><a name="_lab2_3_4"></a></p><h3>4.2 宿主机执行备份</h3>
<ul><li>格式</li></ul>
<div class="jb51code"><pre class="brush:bash;">docker exec 容器名 bash -c '命令1 &amp;&amp; 命令2'</pre></div>
<ul><li>示例</li></ul>
<div class="jb51code"><pre class="brush:bash;">docker exec mysql-8 bash -c 'mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot -p123456 test &gt; /backup/test_20240713.sql'</pre></div>
<p class="maodian"><a name="_lab2_3_5"></a></p><h3>4.3 参数说明</h3>
<ul><li><code>mysqldump</code>: 这是 mysqldump 命令的执行路径或者别名,用于备份 MySQL 数据库。</li><li><code>--single-transaction</code>: 在导出数据时使用单个事务,这样可以确保导出的数据是一个一致性状态的快照,避免了在备份过程中数据变化引起的问题。</li><li><code>--flush-logs</code>: 在备份完成后刷新日志文件,这样可以确保备份包含了最新的日志记录。</li><li><code>--source-data=2</code>: 指定数据来源的格式,这里是指定为默认格式 2,表示在备份过程中,将主服务器的二进制日志位置信息也备份到文件中。这个参数比较重要,用于在恢复数据时找到位置信息。<ul><li>Mysql 8 : <code>--source-data=2</code></li><li>Mysql 5.7 : <code>--master-data=2</code></li></ul></li><li><code>--routines</code>: 备份存储过程和函数。</li><li><code>--opt</code>: 表示使用优化过的备份方式,以提高备份速度和减少备份文件的大小。</li><li><code>-uroot</code>: 使用 root 用户连接到 MySQL 数据库。</li><li><code>-p</code>: 提示输入密码。</li><li><code>test</code>: 要备份的数据库名称,这里假设要备份的数据库名为 test。</li><li><code>&gt; backup.sql</code>: 将导出的 SQL 数据写入到 backup.sql 文件中。</li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>5 定时备份</h2>
<p>使用crontab定时任务来实现定时备份功能</p>
<ul><li>新建个shell脚本<code>mysql-backup.sh</code></li></ul>
<div class="jb51code"><pre class="brush:bash;">#!/bin/bash
docker exec mysql-8 sh -c 'mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot -pn2wqeGrlv7 test &gt; /backup/test_$(date +%Y%m%d_%H%M%S).sql'</pre></div>
<ul><li>进入crontab</li></ul>
<div class="jb51code"><pre class="brush:bash;">crontab -e</pre></div>
<ul><li>添加到定时任务</li><li>每1分钟生效</li></ul>
<div class="jb51code"><pre class="brush:bash;"># mysql备份-每1分钟
*/1 * * * * /workspace/cron-jobs/mysql-backup.sh &gt;&gt; /workspace/cron-jobs/mysql-backup.log 2&gt;&amp;1</pre></div>
<ul><li>每天凌晨3点生效</li></ul>
<div class="jb51code"><pre class="brush:bash;">mysql备份-每天凌晨3点
0 3 * * * /workspace/cron-jobs/mysql-backup.sh &gt;&gt; /workspace/cron-jobs/mysql-backup.log 2&gt;&amp;1</pre></div>
<ul><li>保存即时生效</li></ul>
<div class="jb51code"><pre class="brush:bash;"># 按 shift + :
# 输入 wq </pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>6 恢复数据</h2>
<p><strong>容器内</strong></p>
<p>格式:</p>
<div class="jb51code"><pre class="brush:bash;">mysql -uroot -p密码 数据库 &lt; 备份数据库SQL文件路径</pre></div>
<div class="jb51code"><pre class="brush:bash;">mysql -uroot -p123456 test &lt; /backup/test_20240714_123905.sql</pre></div>
<p><strong>宿主机</strong></p>
<p>格式:</p>
<div class="jb51code"><pre class="brush:bash;">docker exec -i 容器名 mysql -uroot -p密码 数据库 &lt; 备份数据库SQL文件路径</pre></div>
<div class="jb51code"><pre class="brush:bash;">docker exec -i mysql-8 mysql -uroot -p123456 test &lt; /workspace/mysql-8-backup/test_20240714_123905.sql</pre></div>
<p class="maodian"><a name="_label6"></a></p><h2>7 注意事项</h2>
<p class="maodian"><a name="_lab2_6_6"></a></p><h3>7.1 定时备份,出现the input device is not a TTY</h3>
<ul><li><strong>原因:</strong></li></ul>
<p>​ &quot;the input device is not a TTY&quot; 错误通常出现在尝试从非交互式的上下文(比如 cron 任务)中运行需要交互的命令时。</p>
<p>在你的情况下,可能是你的 Shell 脚本 <code>mysql-backup.sh</code> 中包含了需要交互的部分,但是在 cron 任务中无法提供所需的交互。</p>
<ul><li><strong>解决方案:</strong></li></ul>
<p>将脚本中 <code>docker exec -it</code> 中去掉 <code>-it</code> 即可,表示在容器外部执行命令,而不需要进入容器内开启交互终端。</p>
<p class="maodian"><a name="_lab2_6_7"></a></p><h3>7.2 提示</h3>
<blockquote><p>mysqldump: Using a password on the command line interface can be insecure.</p></blockquote>
<p><strong>原因:</strong></p>
<p>命令行不能出现密码 <code>-p123456</code></p>
<p><strong>临时解决方案</strong></p>
<ul><li>设置环境密码,然后命令行不在输入密码</li><li>设置环境密码</li></ul>
<div class="jb51code"><pre class="brush:bash;">export MYSQL_PWD='123456'</pre></div>
<ul><li>去掉密码命令行 <code>-p密码</code></li></ul>
<div class="jb51code"><pre class="brush:bash;">docker exec mysql-8 bash -c 'mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot test &gt; /backup/test_20240713.sql'</pre></div>
<p>​ <code>export MYSQL_PWD=&#39;123456&#39;</code> 是临时性的设置,适合用于测试、临时任务或者当前会话中的需要。</p>
<p>如果你需要更持久的设置,考虑 使用 Dockerfile、Docker Compose 文件或者其他更长久的配置方式来设置环境变量</p>
<p><strong>长期解决方案:</strong></p>
<ul><li>创建容器时候加入<code>-e MYSQL_PASSWORD=密码</code></li></ul>
<div class="jb51code"><pre class="brush:bash;">docker run --name=mysql-8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_PASSWORD=123456 --restart always -v /workspace/mysql-8:/var/lib/mysql -v /workspace/mysql-8-backup:/backup -d mysql:8.0</pre></div>
<ul><li>去掉密码命令行 <code>-p密码</code></li></ul>
<div class="jb51code"><pre class="brush:bash;">docker exec mysql-8 bash -c 'mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot test &gt; /backup/test_20240713.sql'</pre></div>
<p class="maodian"><a name="_label7"></a></p><h2>​总结</h2>
<p>以上为个人经验,希望能给大家一个参考,也希望大家多多支持琼殿技术社区。</p>
頁: [1]
查看完整版本: Docker下Mysql8数据备份与恢复实现