Docker 搭建 Mysql 主从服务器
配置环境如下:
- OS: MacOS
- docker: 24.0.2
- mysql-image: 8.0.33
启动 Master 和 Slave 容器
- 首先创建一个名为 all 的 docker 网络 docker network create all, 便于后续通过容器名进行内部域名访问而非 IP 地址.
- 在 mysql 主从结构中, 每个服务节点的 server-id 需要保证全局唯一, 这里设置 master 节点 server-id=1, 设置 slave 节点 server-id=2
启动 Master 容器
创建 master 的配置文件, master.cnf
touch /home/mac/docker/mysql/master/conf.d/master.cnf
[mysqld]
skip-host-cache
skip-name-resolve
log_bin=master-bin
log_bin_index=master-bin.index
server-id = 1
创建并启动 Master 容器
docker run --name mysql-master \
-p 3306:3306 \
--network all \
--restart always \
-v /home/mac/docker/mysql/master/conf.d:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=master-password \
-d mysql:8.0.33
容器正常启动运行后, 连接 master 节点验证服务是否正常
# 进入 master 容器
docker exec -it mysql-master /bin/bash
# 连接 master 节点
mysql -h mysql-master -u root -p
Password:
# 查看 master 节点的 server-id
SHOW VARIABLES LIKE 'server%'
+----------------+--------------------------------------+
| Variable_name | Value |
+----------------+--------------------------------------+
| server_id | 1 |
| server_id_bits | 32 |
| server_uuid | bd966d86-2977-11ee-824c-0242ac120002 |
+----------------+--------------------------------------+
# 查看 master 节点的 binlog 配置信息
SHOW VARIABLES LIKE 'log_bin%'
+---------------------------------+---------------------------------+
| Variable_name | Value |
+---------------------------------+---------------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/master-bin |
| log_bin_index | /var/lib/mysql/master-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
+---------------------------------+---------------------------------+
启动 Slave 容器
创建 Slave 的配置文件, slave.cnf
touch /home/mac/docker/mysql/master/conf.d/slave.cnf
[mysqld]
skip-host-cache
skip-name-resolve
relay_log=slave-relay
relay_log_index=slave-relay.index
server-id = 2
创建并启动 Slave 容器
docker run --name mysql-slave \
-p 13306:3306 \
--network all \
--restart always \
-v /home/mac/docker/mysql/slave/conf.d:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=slave-password \
-d mysql:8.0.33
测试连通性
进入 slave 容器, 通过 mysql 命令尝试连接 master 节点
# 进入 slave 容器
docker exec -it mysql-master /bin/bash
# 在 slave 容器中尝试连接 master 节点, 可正常连接即表示正常联通
mysql -h mysql-master -u root -p
Password:
# 连接 slave 节点
mysql -h mysql-slave -u root -p
Password:
# 查看 slave 节点的 server-id
SHOW VARIABLES LIKE 'server%';
+----------------+--------------------------------------+
| Variable_name | Value |
+----------------+--------------------------------------+
| server_id | 2 |
| server_id_bits | 32 |
| server_uuid | c171398f-2977-11ee-8386-0242ac120003 |
+----------------+--------------------------------------+
# 查看 slave 节点的 relay-log 配置信息
SHOW VARIABLES LIKE 'relay%';
+---------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------+----------------------------------+
| relay_log | slave-relay |
| relay_log_basename | /var/lib/mysql/slave-relay |
| relay_log_index | /var/lib/mysql/slave-relay.index |
| relay_log_info_file | relay-log.info |
| relay_log_info_repository | TABLE |
| relay_log_purge | ON |
| relay_log_recovery | OFF |
| relay_log_space_limit | 0 |
+---------------------------+----------------------------------+
在 Master 中创建拥有复制权限的用户
连接 Mysql 的 Master 节点上并执行如下语句,创建拥有复制权限的用户 repl 注意: 拥有复制权限的用户密码在设置时,需要使用 mysql_native_password 身份验证插件. MySQL8.0 版本中默认使用 caching_sha2_password 身份验证插件, slave 验证时使用的是 mysql_native_password 如果不匹配会导致 slave 无法正常连接 master
# 查看当前默认的身份验证插件
SHOW VARIABLES LIKE 'default_auth%';
+-------------------------------+-----------------------+
| Variable_name | Value |
+-------------------------------+-----------------------+
| default_authentication_plugin | caching_sha2_password |
+-------------------------------+-----------------------+
-- 创建 repl 用户
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'slave-password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES ;
成功创建拥有复制权限的用户用户后, 执行 SQL SHOW MASTER STATUS 查看 Master 节点的当前 log-bin 信息, slave 节点开启复制时需要用到该信息.
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000003 | 819 | | | |
+-------------------+----------+--------------+------------------+-------------------+
开启 Slave 复制
连接 Slave 节点, 在 Slave 节点中执行如下 SQL 语句, Mysql 8.0.23 版本之后配置 Slave 复制的方式与之前有一些区别, 具体如下:
-- 8.0.23版本之前使用该方式配置 Maste 信息
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='slave-password',
MASTER_LOG_FILE='master-bin.000003',
MASTER_LOG_POS=819;
-- 8.0.23 版本开始采用下面的方式配置 Master 信息
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='mysql-master',
SOURCE_USER='repl',
SOURCE_PASSWORD='slave-password',
SOURCE_LOG_FILE='master-bin.000003',
SOURCE_LOG_POS=819;
根据自己的 MySQL 版本信息选择合适的方式配置好 master-slave 的复制信息后, 开启复制.
具体开启复制并查看 slave 节点状态的语句如下, 根据 mysql 版本选择合适的语句.
-- MySQL 8.0.22 之前
START SLAVE;
SHOW SLAVE STATUS\G;
-- MySQL 8.0.22 开始:
START REPLICA;
SHOW REPLICA STATUS\G;
配置成功则 Slave_IO_Running 和 Slave_SQL_Running 两项的值均为 YES , 可以开始验证.
配置成功显示结果如下:
Slave_IO_State | Waiting for source to send event
Master_Host | mysql-master
Master_User | repl
Master_Port | 3306
Connect_Retry | 60
Master_Log_File | master-bin.000003
Read_Master_Log_Pos | 819
Relay_Log_File | slave-relay.000002
Relay_Log_Pos | 327
Relay_Master_Log_File | master-bin.000003
Slave_IO_Running | Yes
Slave_SQL_Running | Yes
Replicate_Do_DB |
Replicate_Ignore_DB |
Replicate_Do_Table |
Replicate_Ignore_Table |
Replicate_Wild_Do_Table |
Replicate_Wild_Ignore_Table |
Last_Errno | 0
Last_Error |
Skip_Counter | 0
Exec_Master_Log_Pos | 819
Relay_Log_Space | 533
Until_Condition | None
Until_Log_File |
Until_Log_Pos | 0
Master_SSL_Allowed | No
Master_SSL_CA_File |
Master_SSL_CA_Path |
Master_SSL_Cert |
Master_SSL_Cipher |
Master_SSL_Key |
Seconds_Behind_Master | 0
Master_SSL_Verify_Server_Cert | No
Last_IO_Errno | 0
如果 slave 复制连接错误, 可以通过执行停止并重置 slave 复制, 将错误解决后重新配置并开启 slave 复制即可. 停止并重置 slave 复制的语句如下:
-- MySQL 8.0.22 之前
STOP SLAVE;
RESET SLAVE;
SHOW SLAVE STATUS\G;
-- MySQL 8.0.22 开始:
STOP REPLICA;
RESET REPLICA;
SHOW REPLICA STATUS\G;
验证主从同步
在 master 节点和 salve 节点分别执行 SHOW DATABASES;, 显示结果均为:
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
在 master 节点新建数据库 test, 在 salve 节点查看复制结果
-- 在 master 节点新建数据库 test
CREATE DATABASE test;
-- 在 slave 节点查看数据库
SHOW DATABASES ;
主从复制正常执行时, slave 节点的显示结果如下:
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
master-slave 复制已经初步搭建完成.
需要注意的是,如果是给已经运行了一段时间的 mysql 节点添加 slave 节点, 需要先在主节点执行 FLUSH TABLES WITH READ LOCK; 刷新所有表并锁定数据库, 然后将主节点数据库备份复制到目标 slave 节点, 备份复制成功并开启 slave 复制后, 在主节点执行 UNLOCK TABLES;