1. MySQL 主从搭建 —— 基础篇

发布于 2023-09-27
顾名思义,主从复制就是将一个数据库的数据复制到另一个数据库,这里的数据库可以是同一台服务器上的,也可以是不同服务器上的。本章会先介绍如何快速搭建一个主从复制的环境,然后再介绍主从复制的原理和常见的配置方式。 1 基础环境介绍 任意安装了 Docker 和 Docker Compose 的操作系统。 MySQL *…

顾名思义,主从复制就是将一个数据库的数据复制到另一个数据库,这里的数据库可以是同一台服务器上的,也可以是不同服务器上的。本章会先介绍如何快速搭建一个主从复制的环境,然后再介绍主从复制的原理和常见的配置方式。

1 基础环境介绍

  • 任意安装了 DockerDocker Compose 的操作系统。
  • MySQL 5.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 格式,但可能会占用大量存储

masterslave 两者的配置文件不同点是:

  • 从库增加了 read_only 限制了只读,需要注意该选项只能限制平台用户,限制不了 root 权限用户。为了避免误操作,建议启动通过 set global super_read_only=true;(重启 MySQL 后失效),这样会限制 root 权限用户也无法进行写入操作。(之所以没有把这个选项配置到配置文件中将限制无法进行连接)
  • 集群中不同服务的 server_id 应避免重复。
  • 其他的参数值都一样,不过也都是重要参数,详细作用可看配置文件后的注释。

这里 masterslave 的配置文件只是默认配置,下面介绍不同的部署方式会在这个默认配置文件的基础上修改(会注明修改内容)。

然后在 docker-compose.yml 文件所在目录下执行 docker-compose up -d 即可启动服务。

3 常见启动报错

如果你启动过程报错了,可以在这里找找解决方案,正常启动的话,跳过这一步。

3.1 windows wsl 内启动失败

如果你使用的是 windowswsl,那么也可能会遇到无法启动的问题,报错信息有:

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.cnfchmod 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 验证同步

可在主库上建库、建表,插入数据等操作,从库应该会自动同步过来。