1. MySQL 主从搭建 —— 基础篇
顾名思义,主从复制就是将一个数据库的数据复制到另一个数据库,这里的数据库可以是同一台服务器上的,也可以是不同服务器上的。本章会先介绍如何快速搭建一个主从复制的环境,然后再介绍主从复制的原理和常见的配置方式。
1 基础环境介绍
- 任意安装了
Docker和Docker Compose的操作系统。 MySQL5.7-8.0 均可,我这里采用8.0版本,但主从版本尽量要保持一致,否则可能会出现问题。
2 配置文件介绍
MySQL 将使用 docker-compose 安装,文件目录结构为:
.
├── docker-compose.yml # docker-compose 配置文件,描述主从服务信息
├── master
│ ├── conf
│ │ └── my.cnf # master 节点的 mysql 配置文件
│ └── data # master 节点的数据目录,包含 binlog、redo-log、relay-log 等文件
└── slave
├── conf
│ └── my.cnf # master 节点的 mysql 配置文件
└── data # master 节点的数据目录,包含 binlog、redo-log、relay-log 等文件根目录下有 docker-compose.yml 文件,然后有个 master 文件夹,还有个 slave 文件夹,里面包含 conf 配置文件和 data 数据目录。
其中 docker-compose.yml 文件内容如下:
version: '3.1'
services:
mysql-master:
image: mysql:8.0 # master 指定版本号为 8.0
container_name: mysql-master # master 容器名称
restart: always
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: uxUw.SyCs)bb # master root 密码
MYSQL_ROOT_HOST: '%' # master 允许 root 在任意主机远程登录,% 表示任意主机,可以指定具体的 IP 或 IP 段
MYSQL_DATABASE: my-db # 初始化创建的数据库名称
MYSQL_USER: my-db-user # 初始化创建的普通数据库用户,将自动授予默认数据库所有权限
MYSQL_PASSWORD: uxUw.SyCs)bb # 初始化创建的普通数据库用户的密码
ports:
- '53306:3306' # master 容器对外暴露的端口号
volumes:
- ./master/data/:/var/lib/mysql/
- ./master/conf/:/etc/mysql/conf.d/
# slave 的配置与 master 类似,这里不再赘述
mysql-slave:
image: mysql:8.0
container_name: mysql-slave
restart: always
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: uxUw.SyCs)bb
MYSQL_ROOT_HOST: '%'
MYSQL_DATABASE: my-db
MYSQL_USER: my-db-user
MYSQL_PASSWORD: uxUw.SyCs)bb
ports:
- '53307:3306'
volumes:
- ./slave/data/:/var/lib/mysql/
- ./slave/conf/:/etc/mysql/conf.d/master/conf/my.cnf 配置文件:
[mysqld]
# 集群相关配置:
server_id = 1 # server-id,集群中不同服务之间,不应重复
skip_slave_start = true # 禁止自动开启复制功能,建议手动操作
log_slave_updates = true # 是否将从库收到的变更事件重新写入到自己的 binlog 中,建议开启。不然将从库切换为主库时,或者该从库作为其他从库的数据源时,将会出现问题。
# 数据存储格式和名称:
log_bin = mysql-bin # binlog 的存储文件名,也可以写绝对路径。否则将存储在默认目录下
relay_log = mysql-relay-bin # 中继日志的存储文件名,也可以写绝对路径。否则将存储在默认目录下,默认时 hostname-relay-bin
binlog_format = row # 采用更安全可靠的 row 格式,但可能会占用大量存储slave/conf/my.cnf 配置文件:
[mysqld]
# 从库配置
read_only = true # 从库只读
# 集群相关配置:
server_id = 2 # server-id,集群中不同服务之间,不应重复
skip_slave_start = true # 禁止自动开启复制功能,建议手动操作
log_slave_updates = true # 是否将从库收到的变更事件重新写入到自己的 binlog 中,建议开启。不然将从库切换为主库时,或者该从库作为其他从库的数据源时,将会出现问题。
# 数据存储格式和名称:
log_bin = mysql-bin # binlog 的存储文件名,也可以写绝对路径。否则将存储在默认目录下
relay_log = mysql-relay-bin # 中继日志的存储文件名,也可以写绝对路径。否则将存储在默认目录下,默认时 hostname-relay-bin
binlog_format = row # 采用更安全可靠的 row 格式,但可能会占用大量存储master 和 slave 两者的配置文件不同点是:
- 从库增加了
read_only限制了只读,需要注意该选项只能限制平台用户,限制不了 root 权限用户。为了避免误操作,建议启动通过set global super_read_only=true;(重启 MySQL 后失效),这样会限制 root 权限用户也无法进行写入操作。(之所以没有把这个选项配置到配置文件中将限制无法进行连接) - 集群中不同服务的
server_id应避免重复。 - 其他的参数值都一样,不过也都是重要参数,详细作用可看配置文件后的注释。
这里
master和slave的配置文件只是默认配置,下面介绍不同的部署方式会在这个默认配置文件的基础上修改(会注明修改内容)。
然后在 docker-compose.yml 文件所在目录下执行 docker-compose up -d 即可启动服务。
3 常见启动报错
如果你启动过程报错了,可以在这里找找解决方案,正常启动的话,跳过这一步。
3.1 windows wsl 内启动失败
如果你使用的是 windows 的 wsl,那么也可能会遇到无法启动的问题,报错信息有:
mysql-master | 2023-09-11T06:44:31.139281Z 0 [ERROR] [MY-010295] [Server] Could not set file permission for ca.pem
mysql-master | 2023-09-11T06:44:31.139281Z 0 [ERROR] [MY-010295] [Server] Could not set file permission for private_key.pem
mysql-master | 2023-09-11T06:44:31.139316Z 0 [ERROR] [MY-010119] [Server] Aborting可以通过在 wsl 内配置文件 /etc/wsl.conf 内增加(没有这个配置文件则创建):
[automount]
enabled = true
options = "metadata"
mountFsTab = false然后重启 wsl,再尝试即可解决。
4 主从技术
4.1 验证配置文件生效
前面我们通过 docker-compose up -d 启动了服务,现在我们需要连接 MySQL 并验证配置文件中的配置项是否生效,这很重要,不然你后续做的操作可能都是无用功。
验证方式通过 show variables 命令,如 show variables like '%server_id%';,master 服务器上应该返回 1,slave 服务器上应该返回 2。
如果配置文件未生效,这里提一个可能的原因,如果在启动日志中有日志:
mysqld: [Warning] World-writable config file '/etc/mysql/conf.d/my.cnf' is ignored.,这表示忽略了你的配置文件而使用了默认配置,原因是 MySQL 对配置文件有权限要求,需要是0444权限,Linux 的话,可以通过chmod 0444 master/conf/my.cnf和chmod 0444 slave/conf/my.cnf来设置主从的配置文件权限。
4.2 配置主从
分别连接主从两个库(都使用 root 用户)。
4.2.1 在主库创建用于同步的账号
在主库上执行以下命令,创建一个用于同步的账号 repl,允许所有主机 % 可访问,密码为 uxUw.SyCs)bb,并授予 REPLICATION SLAVE 权限,最后刷新权限:
CREATE USER 'repl'@'%' IDENTIFIED BY 'uxUw.SyCs)bb';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;4.2.2 确认开始同步的位置
在主库执行命令查看主库的 binlog 当前文件名和位置:
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 879 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)4.2.3 在从库配置主库信息
在从库上配置从主库同步使用的信息:
CHANGE MASTER TO
MASTER_HOST = 'mysql-master',
MASTER_PORT = '3306',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'uxUw.SyCs)bb',
MASTER_LOG_FILE = 'mysql-bin.000003',
MASTER_LOG_POS = 879;各个参数含义如下:
MASTER_HOST:主库的 IP 地址或域名,由于这里使用的是docker-compose,他们在同一个docker-compose.yml文件中声明,所以可以直接使用容器名称mysql-master互相访问。MASTER_PORT:主库的端口号。MASTER_USER:用于从主库复制的账号。MASTER_PASSWORD:用于从主库复制的账号的密码。MASTER_LOG_FILE:主库的 binlog 当前文件名,表示从库从主库的哪个 binlog 文件开始复制,这里参考上一步我们从主库获取到的信息。MASTER_LOG_POS:主库的 binlog 当前位置,表示从库从主库指定 binlog 的哪个位置开始复制,这里参考上一步我们从主库获取到的信息。
4.2.4 从库启用同步
由于我们在 my.conf 中配置的参数 skip_slave_start 为 true,所以需要手动启动同步,且非常建议手动启动,这样可以避免不可预知的情况导致从库自动启动同步,从而导致数据丢失。
START SLAVE;4.2.5 验证同步
可在主库上建库、建表,插入数据等操作,从库应该会自动同步过来。