主从备份是容灾的一种手段, 模拟主从备份可以有下面几种方式:
binlog
是MySQL数据库的二进制日志,用于记录用户对数据库操作的SQL语句(不包括 SELECT
),可以在配置文件开启,也可以在 MySQL 客户端开启. 可以在客户端键入show plugins;
查看 binlog
是否已安装开启( Active )
+----------------------------+----------+--------------------+---------+---------+
| Name | Status | Type | Library | License |
+----------------------------+----------+--------------------+---------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
必须安装有 docker
及 docker-compose
用于构建容器环境, 本测试在 Ubuntu 16.04 及下列版本下进行, 使用其他版本可能会有使用差异.
docker-compose 1.25.4
docker 19.03.6
有关安装的细节, 请搜索相关关键词, 或者直接根据 Docker 官方文档 进行安装
由于众所周知的原因, 拉取镜像时可能会很慢, 推荐设置国内的镜像源进行加速
在 Ubuntu/Centos/Debian
下修改或创建此文件 /etc/docker/daemon.json
示例文件内容如下, 可以自由添加镜像源. 镜像源有可能会宕机, 镜像源测试请参阅docker-registry-cn-mirror-test
{
"registry-mirrors":[
"https://dockerhub.azk8s.cn",
"https://docker.mirrors.ustc.edu.cn",
"https://reg-mirror.qiniu.com"
],
"debug": true,
"experimental": false
}
Dockerfile
是一个文本文件, 只需要 touch Dockerfile
创建即可.docker-compose.yml
是用于运行多个 Docker 容器的配置文件, 使用 yaml
语言.如只准备测试一主一从, 那么移除 slave02
目录, 添加多个从服务器则相应增加文件夹.
├── docker-compose.yml
├── master
│ ├── Dockerfile
│ └── my.cnf
├── slave01
│ ├── Dockerfile
│ └── my.cnf
└── slave02
├── Dockerfile
└── my.cnf
environment
在创建 MySQL 密码时, 测试用途用 root
没问题, 其他时候记得创建复杂密码, 至少可以使用 uuidgen
命令生成.
支持在创建时同时创建一个数据库, 创建多个或进行其他数据初始化, 建议依靠外部 SQL
文件.links
这个不是推荐的配置方式, 不利于扩展, 但在此处我们只是用于测试. 可以自由添加你要的从服务器名称, 用于容器间的连接. 更推荐配置 networks
ports
冒号左边为暴露的端口, 右边为容器内部的端口号, 在不配置网络的情况下(此时默认为 127.0.0.1
), 为了避免端口冲突, 必须使暴露的端口号不一致.version: '2'
services:
mysql-master:
build:
context: ./ # 声明构建的文件夹
dockerfile: master/Dockerfile # 声明 Docker 文件目录
environment: # 环境变量, 支持数组或列表方式
- "MYSQL_ROOT_PASSWORD=root"
- "MYSQL_DATABASE=db0" # 初始创建的数据库
links:
- mysql-slave01
- mysql-slave02
ports:
- "33065:3306"
restart: always
hostname: mysql-master
mysql-slave01:
build:
context: ./
dockerfile: slave/Dockerfile
environment:
- "MYSQL_ROOT_PASSWORD=6954D5F0"
- "MYSQL_DATABASE=db0"
ports:
- "33066:3306"
restart: always
hostname: mysql-slave01
mysql-slave02:
build:
context: ./
dockerfile: slave02/Dockerfile
environment:
- "MYSQL_ROOT_PASSWORD=6954D5F0"
- "MYSQL_DATABASE=db0"
ports:
- "33067:3306"
restart: always
hostname: mysql-slave02
FROM
指定了基础镜像, 可以根据需求更改 MySQL 镜像版本COPY
将源文件复制到目标容器, 从服务器相应地创建 Dockerfile
, 修改源文件位置. 也可以使用 ADD
这个更高级的复制命令, 但没必要.FROM mysql:5.7.17
COPY ./master/my.cnf /etc/mysql/my.cnf
# master/my.cnf
[mysqld]
## 设置server_id,注意要唯一
server_id=100
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 开启二进制日志功能,可以随便取,最好有含义
log-bin=replicas-mysql-bin
## 为每个session分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
Slave 节点的配置与 Master 相似, 但每个节点的 server_id
必须不同, 此外增加了 relay_log
中继日志的配置以及只读的设置
[mysqld]
## 设置server_id,注意要唯一
server_id=101
# ... 省略配置
## relay_log配置中继日志
relay_log=replicas-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## 防止改变数据(除了特殊的线程)
read_only=1
进入有 docker-compose.yml
的目录, 执行以下命令
该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作, -d
表示后台运行镜像.
docker-compose up -d
之后执行docker ps
查看正在运行的镜像, 如果是一主一从, 可以看到至少两个正在运行的镜像
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef799b7d8cf8 mstest_mysql-master "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:33065->3306/tcp mstest_mysql-master_1
9d7ea93b7a85 mstest_mysql-slave "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:33066->3306/tcp mstest_mysql-slave_1
键入 docker exec -it [name/id] /bin/bash
进入容器, 可以是容器名称也可以是容器 id, 如下方示例:
docker exec -it mysql-master_1 /bin/bash
可以直接进入容器再进入 mysql
配置, 也可以不进入, 直接在终端键入下方命令, port
就是 docker-compose.xml
设置的端口号, 例如前面 master
的 33065
mysql -uroot -p -P[port] -h127.0.0.1
键入 show master status;
记住当前 File
的名称和 Position
, 这是从节点进行 binlog
复制找点用的.
mysql> show master status
-> ;
+---------------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------------+----------+--------------+------------------+-------------------+
| replicas-mysql-bin.000003 | 154 | | mysql | |
+---------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec
这里设置复制主节点的相关信息, 在前面文件用的是 root
密码,因此这里也是 root
用户, 将MASTER_LOG_FILE
和 MASTER_LOG_POS
填上相应信息
CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='root', MASTER_PASSWORD='root', MASTER_LOG_FILE='replicas-mysql-bin.000003', MASTER_LOG_POS=154;
接着启动复制.
start slave;
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...同样地, 如果有多个 Slave 节点, 就这一步多做几次.show slave status\G;
查看是否启用成功, 关注Slave_IO_Running
和 Slave_SQL_Running
是否为 Yes
回到 Master 节点, 创建一个数据库 或者 往已经创建好的 db0
写入数据,
mysql> create database db1;
回到 Slave 节点, 查看两边是否同步.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db0 |
| db1 |
GTID 自 MySQL 5.6.MySQL 5.6.5 便引入了,中文叫全局事务 ID(Global Transaction ID)
在本文的基于二进制日志复制中,从库需要告知主库要从哪个偏移量(就是 Log File 的 Position)进行增量同步,如果指定错误会造成数据的遗漏,从而造成数据的不一致。
但有了 GTID,发生主备切换时,MySQL 的其它从库可以自动在新主库上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制位置发生误操作的风险。另外,基于 GTID 的复制还可以忽略已经执行过的事务。
公众号:程序员的碎碎念
Github:github.com/FesonX
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。