Docker 搭建 Mysql 主从服务器

181 阅读4分钟

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_RunningSlave_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;