MySQL 主从复制

本文演示一个简单的 MySQL 主从复制的示例。

0. 说明

  1. 本示例为一主一从的架构。
  2. 使用 Docker 启动两个 MySQL 容器来做演示,确保已经安装了 Docker,并且懂得 Docker 的基本用法。

1. 创建并启动容器

主库:

docker run --name=mysql-dn-m  --env=MYSQL_ROOT_PASSWORD=admin123 -p 3316:3306 -p 33160:33060  -d mysql:latest

从库

docker run --name=mysql-dn-s --env=MYSQL_ROOT_PASSWORD=admin123 -p 3326:3306 -p 33260:33060 --link mysql-dn-m:master -d mysql:latest

以上操作的说明:

  1. 启动两个 MySQL 容器(镜像的具体信息可以在这里查看),主库容器命名为 mysql-dn-m,从库容器命名为 mysql-dn-s
  2. 设置 root 用户的密码为 admin123(只作为演示实用)。
  3. 映射相应的端口号。
  4. 在从库容器创建时,使用 --link mysql-dn-m:master 创建从库容器到主库容器的网络连接,这样可以在从库内以 master 为主机名,访问主库。

使用 docker ps 命令,查看当前正在运行的容器,保证以上操作正常。

1. 主库配置

使用 docker exec -it mysql-dn-m /bin/bash 命令进入主库容器的命令行。编辑 /etc/mysql/my.cnf 配置文件。

首先,在 [mysqld] 的下方,添加一下配置(# 符号后面的内容为注释):

log-bin=mysql-bin # 开启二进制日志
server-id=1 # 设置唯一的 server-id

然后在配置文件的最后添加如下内容:

binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema
binlog-ignore-db=sys

这样可以忽略复制 MySQL 内置的四个数据库。

如果需要自定义复制的库,可以用 binlog-do-db 参数来配置,不配置的话,默认复制所有库。

操作完以后重启主库容器。

可以连接主库,执行一下 SQL 语句,查看日志的开启状态。

show variables like '%log_bin%';

如果 log_bin 的值是 ON,则表示没有问题。

2. 从库配置

使用与主库同样的方法,编辑从库容器中的 /etc/mysql/my.cnf 配置文件。从库的配置只需要在 [mysqld] 的下方添加一行即可:

server-id=2 # 设置唯一的 server-id

操作完以后重启从库容器。

3. 在主库创建用与数据同步的用户账号

进入主库。

执行如下命令创建用户,用户名、主机、密码按需设置,然后记住:

CREATE USER 'repl'@'%' IDENTIFIED BY 'slavepass';

然后,为刚刚创建的用户授权:

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'

最后刷新权限:

flush privileges;

完成后,可以使用下面的查询语句来验证这一步的操作:

show grants for 'repl';

4. 配置主从复制

先连接主库,执行一下查询操作:

show master status\G;

查询结果类似以下内容:

***************************[ 1. row ]***************************
File              | mysql-bin.000009
Position          | 435
Binlog_Do_DB      |
Binlog_Ignore_DB  | mysql,information_schema,performance_schema,sys
Executed_Gtid_Set |

记下 FilePosition 的值。

连接从库,使用之前创建的用户,和刚刚记下的两个值,执行以下操作来创建复制:

change master to MASTER_HOST = 'master', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = 'slavepass', MASTER_LOG_FILE = 'mysql-bin.000009', MASTER_LOG_POS = 435;

参数说明:

  1. MASTER_HOST:主库的主机,可以是 IP 或者主机名,这里输入我们之前配置的 master
  2. MASTER_PORT:主库的端口号,使用默认端口号时可以省略这个参数。
  3. MASTER_USER:之前配置的用于复制的用户名。
  4. MASTER_PASSWORD:之前配置的用于配置的用户密码。
  5. MASTER_LOG_FILE:之前记下的主库日志文件名。
  6. MASTER_LOG_POS:之前记下的主库日志位置。

执行以上语句后,就创建成功了。可以在从库上执行以下查询语句验证主从复制的状态:

show slave status\G;

如果 Slave_IO_RunningSlave_SQL_Running 两项的值都是 Yes 就说明成功了。

如果没有成功,查询结果中的相应字段也会给出失败的信息,供排查错误。我在配置的过程中遇到了 Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection 的错误,通过 Google 搜索,在主库执行了 ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'slavepass'; 语句解决了问题,这个应该是验证方式不匹配导致从库连接主库失败。

其他导致连接不成功的错误还包括容器之间网络不通、用户名密码或者权限配置错误、日志文件和位置配置错误等,出错时可以排查一下这些内容。

5. 测试验证

至此就配置完成了,可以在主库创建数据库、表,或者插入、修改、删除数据来验证配置是否成功。

6. 如果一个数据库挂掉了怎么办?

如果从库挂掉了,主库内容发生了变化,在从库再次启动后,会自动同步期间发生变化的数据。

在此主要说明一下主库挂掉以后,怎样重新建立数据同步。

首先,重新查看主库日志文件和位置:show master status\G

然后在从库执行如下步骤:

  1. 停止复制:stop slave
  2. 重新配置主从复制的参数:change master to MASTER_HOST = 'master', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = 'slavepass', MASTER_LOG_FILE = 'mysql-bin.000009', MASTER_LOG_POS = 435;
  3. 启动复制:start slave;

立 FLAG:

  • 🚩研究一下前面提到的用户认证出问题的原理。
  • 🚩研究主从复制的更多细节问题。
  • 🚩写篇 Docker 入门的文。