Docker MySQL 主从复制设置


这篇文章我们将使用 Docker 学习 MySQL 主从复制功能。

docker-mysql-master-slave 仓库中包含了基于 Docker 的 MySQL 复制示例的配置和说明。

先决条件

  • 您已经安装了Docker v.18或更高版本。
  • 安装了 docker-compose v1.23 或更高版本。
  • 非常基础的MySQL知识。

一些理论

MySQL 复制是一种特殊设置,涉及两个或多个 MySQL 服务器,其中一个数据库服务器(称为主服务器或源服务器)复制到另一个数据库服务器(称为从服务器或副本服务器)。副本同步过程是通过从源二进制日志中复制和执行 SQL 语句来完成的。 MySQL 配置允许选择整个源数据库或仅将特定表复制到副本。

默认情况下,MySQL复制的同步类型是异步的(单向的),这意味着“副本”不会通知它的“源”关于复制和处理事件的结果。其他类型的同步(半同步、同步)可以通过插件或特殊设置(如NDB Cluster)获得

使用 MySQL 复制,您可以进行一些特定的配置类型:链式复制、循环复制(也称为主-主或环式复制)以及这些类型的组合。限制条件是复制只能有一个源服务器。

  • 链式复制是指数据库服务器之间有一个链。例如:源 1 - > 副本 1 - > 副本 2。副本 1 是副本 2 的源,是源 1 的副本。当副本 1 包含一个 “合并 “数据库(由 “源 “表和它自己的 “添加 “表组成)时,这种复制就很有用。

  • 循环复制假设在循环中有主数据库,同时也充当副本。示例:Master← → Master。这里的问题是列同步自动递增。解决方法是配置 “auto_increment_increment “和 “auto_increment_offset “服务器变量,根据每个主服务器的设置,以不同的步长或范围进行递增。如果使用 InnoDB,请考虑到在环形复制时,行不会总是被添加到副本索引的末尾,在这种情况下,由于聚类索引排序的原因,可能会导致在副本上出现额外的插入延迟。

实践

创建一个空目录并克隆存储库。

mkdir mysql-master-slave
cd mysql-master-slave
git clone https://github.com/vbabak/docker-mysql-master-slave ./
./build.sh

构建过程要求您的系统上未使用端口 4406 和 5506。否则,您可以将其更新为 docker-compose.yml 文件中任何未使用的端口并重新运行构建脚本。

如果一切顺利,你会收到这样的信息:等待mysql_master数据库连接…,最后是副本(slave)状态报告。

最后一行表示它正在等待来自 master 的新更新。

要测试复制是否正常工作,请在 Master 上运行以下查询:

docker exec -it mysql_master bash
mysql -u root -p'111' mydb
mysql> create table if not exists code(code int);
# Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> insert into code values (100), (200);
# Query OK, 2 rows affected (0.01 sec)

并检查副本:

docker exec -it mysql_slave bash
mysql -u root -p'111' mydb
mysql> select * from code;
+------+
| code |
+------+
|  100 |
|  200 |
+------+

Master configuration

主服务器配置放在 “master/conf/mysql.conf.cnf “中。下面是一些解释。前两个选项用于提高服务器性能,与复制设置本身无关。

  • skip-host-cache

    禁用内部主机缓存,以加快名称到 IP 的解析速度。

  • skip-name-resolve

    禁用 DNS 主机名查询

  • server-id = 1

    对于复制中使用的服务器,必须指定一个唯一的服务器 ID。它必须不同于任何其他源或副本使用的其他 ID。

  • log_bin = /var/log/mysql/mysql-bin.log

    启用 bin 日志并设置二进制日志文件的基本名称和路径(如 log_bin_basename)。

  • binlog_format = ROW
    可能的值是 ROW(副本仅重播行上的实际更改)、STATMENT(副本重播更改数据的所有查询)、MIXED(使用基于语句的复制,除非服务器决定仅基于行的复制可以给出正确的结果,例如复制 GUIID() 的结果)。

  • binlog_do_db = mydb

    指定一个数据库,哪些语句将写入二进制日志文件。

    与在 docker 容器中启动 MySQL 相关的环境参数放置在“master/mysqlmaster.env”文件中。它们在 [mysql:5.7](https://hub.docker.com//mysql)镜像的 docker hub 网站上有描述。

如果您是 Windows 用户,build.sh 脚本可能无法工作,因此您需要通过创建 mydb_slave_user 用户来设置主数据库 — 在 Master 上运行 2 个 sql 命令,然后设置从数据库 — 在上运行 2 个 sql 命令复制品,请参阅下面的详细信息。

最后,在主服务器上添加复制用户。创建一个具有 REPLICATION SLAVE 权限的新用户进行复制:

# SETUP MASTER SQL COMMANDS
GRANT REPLICATION SLAVE ON *.* TO "mydb_slave_user"@"%" IDENTIFIED BY "mydb_slave_pwd";
FLUSH PRIVILEGES;

Replica configuration

部分配置参数会重复主数据库。

  • relay-log = /var/log/mysql/mysql-relay-bin.log

    包含从源二进制日志读取的数据库事件。

启动副本。

首先,你需要找到一个master主机的ip地址。您可以检查主控主机上的“hosts”文件

docker exec -it mysql_master cat '/etc/hosts'

output:

127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
192.168.16.2	617f30b23d6b

一行将包含 IP 地址,例如:172.19.0.2。这是一个MASTER_HOST。

其次,从此命令中查找日志文件和位置:

docker exec mysql_master sh -c 'export MYSQL_PWD=111; mysql -u root -e "SHOW MASTER STATUS \G"'

output:

*************************** 1. row ***************************
             File: mysql-bin.000003
         Position: 1040
     Binlog_Do_DB: mydb
 Binlog_Ignore_DB:
Executed_Gtid_Set:

“File:”为MASTER_LOG_FILE,“Position:”为MASTER_LOG_POS。

现在,当我们拥有所有变量后,我们可以修改并运行以下命令来启动复制:

# SETUP REPLICA SQL COMMANDS
CHANGE MASTER TO MASTER_HOST='${IP}', MASTER_USER='mydb_slave_user', MASTER_PASSWORD='mydb_slave_pwd', MASTER_LOG_FILE='${LOG}', MASTER_LOG_POS=$POS;
START SLAVE;

复制不安全语句和非确定性查询

在 MySQL 复制中,语句的 “安全性 “是指该语句及其效果能否使用基于语句的格式正确复制。如果语句是确定性的,那么它就是安全的。确定性是指语句总是产生相同的结果。使用基于语句的日志记录时,标记为不安全的语句会产生警告。在此查看不安全语句列表。示例found_rows()、rand()、uuid()。

对于行级复制,不区分确定性和非确定性语句。基于行的复制的缺点是,当 WHERE 子句匹配大量行时,范围更新的成本会很高。

关闭 Docker 容器

总结

复制是任何数据库的强大组成部分,幸运的是 MySQL 支持它。

使用范围广泛。它可用于高可用性和数据分发、数据备份、负载平衡。甚至可以根据地理位置优化延迟。

参考


文章作者: 张权
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张权 !
评论
  目录