一、引言
在数据库管理中,MySQL 主从复制是一种非常重要的技术,它可以实现数据的备份、读写分离,减轻主数据库的压力。本文将详细介绍如何使用 Docker 和 Harbor 仓库来搭建 MySQL 主从复制环境,适合刚接触数据库和 Docker 的新手学习。
二、MySQL 主从复制原理
2.1 基本概念
主从复制是指一台服务器充当主数据库服务器(Master),另一台或多台服务器充当从数据库服务器(Slave),主服务器中的数据会自动复制到从服务器之中。对于多级复制,数据库服务器既可以充当主机,也可以充当从机。MySQL 主从复制的基础是主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新。
2.2 角色职责
- 主数据库(Master):负责处理写操作和更新数据,是业务操作的主要入口。
- 从数据库(Slave):复制主数据库的数据,通常用于读操作和数据备份,以减轻主数据库的压力。
2.3 复制流程
- 主库记录并发送日志:
- 当主库发生更新事件(如
UPDATE
、INSERT
、DELETE
、CREATE
)时,这些操作会被顺序地写入二进制日志(binlog
)中。 - 主库会开启一个
binlog dump
线程,负责将binlog
日志中的事件发送给从库。
- 当主库发生更新事件(如
- 从库接收并写入中继日志:
- 从库通过
IO
线程连接到主库,并请求binlog
日志的内容。 - 主库的
binlog dump
线程将binlog
日志中的事件发送给从库的IO
线程。 - 从库的
IO
线程接收这些事件,并将其写入到从库的中继日志(relay log
)中。
- 从库通过
- 从库同步数据:
- 从库开启一个
SQL
线程,实时监控relay log
的内容是否有更新。 SQL
线程解析relay log
中的SQL
语句,并在从库上执行这些语句,从而实现数据的同步。
- 从库开启一个
三、拉取 MySQL 镜像
3.1 从 Harbor 仓库拉取镜像
可以使用以下命令从 Harbor 仓库拉取 MySQL 9.3.0 版本的镜像:
[root@mysql docker]# docker pull harbor.registry.com/library/mysql:9.3.0
参数解释:
docker pull
:用于从镜像仓库中拉取镜像。harbor.registry.com/library/mysql:9.3.0
:指定要拉取的镜像的地址和版本,harbor.registry.com
是 Harbor 仓库的地址,library/mysql
是镜像的名称,9.3.0
是镜像的版本号。
如果没有仓库,可以直接执行这个命令:
docker pull mysql:9.3.0
尝试从 Docker Hub(官方 Docker 镜像仓库)拉取 mysql
镜像的 9.3.0
版本。Docker Hub 是 Docker 官方的公共镜像仓库,当你使用 docker pull
命令并且不指定具体仓库地址时,Docker 客户端默认会从 Docker Hub 拉取镜像。
3.2 检查镜像是否拉取成功
使用以下命令查看本地镜像列表:
[root@mysql docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
harbor.registry.com/library/mysql 9.3.0 2c849dee4ca9 5 weeks ago 859MB
参数解释:
docker images
:用于列出本地所有的镜像,显示镜像的仓库名、标签、镜像 ID、创建时间和大小等信息。
3.3 处理拉取镜像时的 TLS 证书验证失败问题
如果在使用 docker pull
命令拉取镜像时,由于 TLS 证书验证失败导致报错,例如:
[root@mysql docker]# docker pull harbor.registry.com/library/mysql:9.3.0
Error response from daemon: Get "https://harbor.registry.com/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
可以创建 /etc/docker/daemon.json
文件,并写入以下内容:
{
"default-ipc-mode": "shareable",
"data-root": "/data/docker",
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "50"
},
"insecure-registries": ["https://harbor.registry.com"],
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.imgdb.de",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com",
"https://docker.1ms.run",
"https://func.ink",
"https://lispy.org",
"https://docker.xiaogenban1993.com"
]
}
参数解释:
default-ipc-mode
:设置默认的 IPC(进程间通信)模式为shareable
。data-root
:指定 Docker 数据存储的根目录为/data/docker
。exec-opts
:设置容器执行时的选项,native.cgroupdriver=systemd
表示使用systemd
作为 cgroup 驱动。log-driver
:指定日志驱动为json-file
,将容器日志以 JSON 文件的形式存储。log-opts
:设置日志的选项,max-size
表示单个日志文件的最大大小为100m
,max-file
表示最多保留50
个日志文件。insecure-registries
:添加不安全的镜像仓库地址,允许从该仓库拉取镜像,这里是https://harbor.registry.com
。registry-mirrors
:设置镜像加速地址,提高镜像拉取的速度。
3.4 添加 Harbor 仓库映射
在 /etc/hosts
文件中添加 Harbor 仓库的映射:
[root@mysql docker]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.220.20 harbor.registry.com harbor
参数解释:
/etc/hosts
:是一个本地的域名解析文件,通过添加192.168.220.20 harbor.registry.com harbor
这一行,将harbor.registry.com
域名映射到192.168.220.20
这个 IP 地址。
注意:
四、启动 MySQL 容器
4.1 启动初始容器
使用以下命令启动一个 MySQL 容器:
[root@mysql docker]# docker run --name mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD="123456" harbor.registry.com/library/mysql:9.3.0
参数解释:
docker run
:用于创建并启动一个新的容器。--name mysql
:为容器指定一个名称为mysql
。-d
:表示在后台运行容器。-p 3306:3306
:将宿主机的3306
端口映射到容器内部的3306
端口,这样可以通过宿主机的3306
端口访问容器内的 MySQL 服务。-e MYSQL_ROOT_PASSWORD="123456"
:设置容器内 MySQL 的 root 用户密码为123456
。harbor.registry.com/library/mysql:9.3.0
:指定要使用的镜像。
4.2 检查容器是否启动成功
使用以下命令查看正在运行的容器:
[root@mysql docker]# docker ps
参数解释:
docker ps
:用于列出正在运行的容器,显示容器的 ID、镜像、命令、创建时间、状态、端口映射和名称等信息。
4.3 查看容器日志
如果容器启动报错,可以使用以下命令查看容器的日志,以寻找出错原因:
[root@mysql docker]# docker logs mysql
参数解释:
docker logs
:用于查看指定容器的日志信息,mysql
是容器的名称。
4.4 进入容器
使用以下命令进入正在运行的容器:
[root@mysql docker]# docker exec -it mysql /bin/bash
参数解释:
docker exec
:用于在运行的容器中执行命令。-it
:表示以交互模式进入容器,-i
保持标准输入打开,-t
分配一个伪终端。mysql
:是容器的名称。/bin/bash
:指定要执行的命令,即进入容器的bash
终端。
bash-5.1# cd etc
bash-5.1# ls
# 找到my.cnf文件
五、配置主从服务器
5.1 复制配置文件
在新的会话窗口中创建两个目录:
[root@mysql docker]# mkdir /data/master/conf -p
[root@mysql docker]# mkdir /data/slave/conf -p
参数解释:
mkdir
:用于创建目录。-p
:表示如果父目录不存在,则先创建父目录。
将刚刚找到的 my.cnf
配置文件,并将其拷贝到 /data/master/conf
目录下:
[root@mysql docker]# cd /data/master/conf/
[root@mysql conf]# docker cp mysql:/etc/my.cnf .
参数解释:
cd etc
:进入容器的etc
目录。ls
:列出当前目录下的文件和文件夹。exit
:退出容器。docker cp
:用于在宿主机和容器之间复制文件,mysql:/etc/my.cnf
表示容器mysql
内的/etc/my.cnf
文件,.
表示当前目录。
5.2 修改配置文件
编辑 /data/master/conf/my.cnf
文件,添加 server-id=1
:
[root@mysql conf]# vim /data/master/conf/my.cnf
参数解释:
vim
:是一个文本编辑器,用于编辑文件内容。server-id=1
:为 MySQL 服务器指定一个唯一的 ID,主服务器的 ID 通常为1
。
将修改后的 my.cnf
文件拷贝到 /data/slave/conf
文件夹下面,并将 server-id
的值改为 2
:
[root@mysql conf]# cp my.cnf ../../slave/conf/
[root@mysql conf]# vim /data/slave/conf/my.cnf
参数解释:
cp
:用于复制文件,my.cnf
是要复制的文件,../../slave/conf/
是目标目录。server-id=2
:从服务器的 ID 需要与主服务器不同,这里设置为2
。
5.3 停止并删除初始容器
退出容器后,停掉并删除初始容器:
bash-5.1# exit
[root@mysql docker]# docker stop mysql
[root@mysql docker]# docker rm mysql
参数解释:
docker stop
:用于停止正在运行的容器,mysql
是容器的名称。docker rm
:用于删除容器,mysql
是容器的名称。
查看发现,容器已经删除,没有任何容器了:
[root@mysql docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
六、创建主服务器
使用以下命令创建主服务器容器:
[root@mysql docker]# docker run -d \
--name mysql-master \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /data/master/conf/my.cnf:/etc/my.cnf \
-p 3306:3306 \
harbor.registry.com/library/mysql:9.3.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
参数解释:
-d
:在后台运行容器。--name mysql-master
:为容器指定名称为mysql-master
。-e MYSQL_ROOT_PASSWORD=123456
:设置容器内 MySQL 的 root 用户密码为123456
。-v /data/master/conf/my.cnf:/etc/my.cnf
:将宿主机的/data/master/conf/my.cnf
文件挂载到容器内的/etc/my.cnf
文件,实现配置文件的持久化。-p 3306:3306
:将宿主机的3306
端口映射到容器内部的3306
端口。harbor.registry.com/library/mysql:9.3.0
:指定要使用的镜像。--character-set-server=utf8mb4
:设置服务器的字符集为utf8mb4
。--collation-server=utf8mb4_unicode_ci
:设置服务器的排序规则为utf8mb4_unicode_ci
。
6.1 进入主服务器容器
使用以下命令进入主服务器容器:
[root@mysql docker]# docker exec -it mysql-master /bin/bash
bash-5.1# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 9.3.0 MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
参数解释:
docker exec -it mysql-master /bin/bash
:以交互模式进入mysql-master
容器的bash
终端。mysql -uroot -p123456
:使用 root 用户和密码123456
登录 MySQL。
6.2 创建用户并授权
在主服务器的 MySQL 中创建一个用于同步的用户,并授予其复制从服务器的权限:
# 创建用户:
mysql> create user 'backups'@'%' identified by '123456';
Query OK, 0 rows affected (0.021 sec)
# 给权限:
mysql> grant replication slave on *.* to 'backups'@'%';
Query OK, 0 rows affected (0.003 sec)
# 刷新权限:
mysql> flush privileges;
Query OK, 0 rows affected, 1 warning (0.003 sec)
参数解释:
create user 'backups'@'%' identified by '123456'
:创建一个名为backups
的用户,允许从任何主机连接,密码为123456
。grant replication slave on *.* to 'backups'@'%'
:授予backups
用户在所有数据库和所有表上的复制从服务器的权限。flush privileges
:刷新权限,使新的权限设置生效。
6.3 查看同步起始位置
使用以下命令查看主服务器的二进制日志状态,获取同步的起始位置:
mysql> show binary log status;
-- 或者
mysql> show binary log status\G;
例如:
mysql> show binary log status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000002 | 863 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.000 sec)
mysql> show binary log status\G;
*************************** 1. row ***************************
File: binlog.000002
Position: 863
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.001 sec)
ERROR:
No query specified
参数解释:
show binary log status
:显示主服务器的二进制日志状态,包括当前正在使用的二进制日志文件、位置等信息。\G
:以垂直格式显示查询结果,方便查看。
七、创建从服务器
7.1 创建从服务器容器
在新的窗口中使用以下命令创建从服务器容器:
[root@mysql conf]# docker run -d \
--name mysql-slave \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /data/slave/conf/my.cnf:/etc/my.cnf \
-p 3307:3306 \
harbor.registry.com/library/mysql:9.3.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
参数解释:
- 大部分参数与创建主服务器容器的参数相同,不同之处在于:
--name mysql-slave
:为容器指定名称为mysql-slave
。-p 3307:3306
:将宿主机的3307
端口映射到容器内部的3306
端口,避免与主服务器的端口冲突。
7.2 进入从服务器容器
使用以下命令进入从服务器容器:
[root@mysql conf]# docker exec -it mysql-slave /bin/bash
bash-5.1# mysql -uroot -p123456
参数解释:
- 与进入主服务器容器的命令和参数解释相同。
7.3 配置主从复制
在从服务器的 MySQL 中配置主从复制:
mysql> CHANGE REPLICATION SOURCE TO \
SOURCE_HOST='192.168.220.198',SOURCE_USER='backups',SOURCE_PASSWORD='123456', \
SOURCE_LOG_FILE='binlog.000002',SOURCE_LOG_POS=863,GET_SOURCE_PUBLIC_KEY=1;
参数解释:
CHANGE REPLICATION SOURCE TO
:用于配置从服务器的复制源。SOURCE_HOST='192.168.220.198'
:指定主服务器的 IP 地址。SOURCE_USER='backups'
:指定用于复制的用户。SOURCE_PASSWORD='123456'
:指定用于复制的用户的密码。SOURCE_LOG_FILE='binlog.000002'
:指定主服务器的二进制日志文件。SOURCE_LOG_POS=863
:指定主服务器二进制日志的起始位置。GET_SOURCE_PUBLIC_KEY=1
:表示获取主服务器的公钥。
7.4 启动复制并查看状态
执行以下命令启动复制,并查看复制状态:
mysql> start replica;
mysql> show replica status\G;
参数解释:
start replica
:启动从服务器的复制进程。show replica status\G
:显示从服务器的复制状态,以垂直格式显示结果,方便查看各个参数的值。
八、验证主从复制
8.1 在主服务器创建测试数据库和表
进入主服务器容器并登录 MySQL:
[root@mysql docker]# docker exec -it mysql-master /bin/bash
bash-5.1# mysql -uroot -p123456
在 MySQL 中创建一个测试数据库和表,并插入一些数据:
mysql> CREATE DATABASE test_db;
Query OK, 1 row affected (0.00 sec)
mysql> USE test_db;
Database changed
mysql> CREATE TABLE test_table (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO test_table (name) VALUES ('test_value');
Query OK, 1 row affected (0.00 sec)
8.2 在从服务器验证数据同步
进入从服务器容器并登录 MySQL:
[root@mysql docker]# docker exec -it mysql-slave /bin/bash
bash-5.1# mysql -uroot -p123456
在 MySQL 中检查是否能看到主服务器创建的数据库和表,以及插入的数据:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test_db |
+--------------------+
mysql> USE test_db;
Database changed
mysql> SELECT * FROM test_table;
+----+------------+
| id | name |
+----+------------+
| 1 | test_value |
+----+------------+
如果能在从服务器看到主服务器创建的数据库、表和插入的数据,说明主从复制配置成功。
九、总结
通过以上步骤,我们成功地使用 Docker 和 Harbor 仓库搭建了 MySQL 主从复制环境,并完成了验证。主从复制可以提高数据库的可用性、读写性能和数据安全性,在实际的生产环境中有着广泛的应用。希望本文对刚接触 MySQL 和 Docker 的新手有所帮助。
以上就是完整的 MySQL 主从复制搭建及验证过程,每一步都有详细的命令参数解释,相信新手也能轻松理解和操作。