Loading... 顾名思义,主从复制就是将一个数据库的数据复制到另一个数据库,这里的数据库可以是同一台服务器上的,也可以是不同服务器上的。本章会先介绍如何快速搭建一个主从复制的环境,然后再介绍主从复制的原理和常见的配置方式。 ## 1 基础环境介绍 - 任意安装了 `Docker` 和 `Docker Compose` 的操作系统。 - `MySQL` **5.7-8.0** 均可,我这里采用 `8.0` 版本,但主从版本尽量要保持一致,否则可能会出现问题。 ## 2 配置文件介绍 `MySQL` 将使用 `docker-compose` 安装,文件目录结构为: ```bash . ├── 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` 文件内容如下: ```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` 配置文件: ```mysql [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` 配置文件: ```mysql [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`,那么也可能会遇到无法启动的问题,报错信息有: ```log 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` 权限,最后刷新权限: ```sql 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 在从库配置主库信息 在**从库**上配置从主库同步使用的信息: ```sql 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,所以需要手动启动同步,且非常建议手动启动,这样可以避免不可预知的情况导致从库自动启动同步,从而导致数据丢失。 ```sql START SLAVE; ``` #### 4.2.5 验证同步 可在**主库**上建库、建表,插入数据等操作,**从库**应该会自动同步过来。 最后修改:2024 年 02 月 20 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请我喝杯咖啡吧。