MySQL8 GTID复制

666 阅读4分钟

强烈要求先看【基于二进制日志文件位置的复制】再看这个
为了方便测试,这里使用docker运行测试

参考文档

环境版本说明

Ubuntu 20.04
Docker 19.03.13
MySQL: 8.0.26

db1: 主服务master
db2: 从服务slave

MySQL复制

  • 数据库复制本质上就是数据同步。MySQL 数据库是基于二进制日志(binary log)进行数据增量同步,而二进制日志记录了所有对于 MySQL 数据库的修改操作

MySQL复制类型

MySQL复制类型.png

异步复制

  • GTID复制是异步复制,Master不关心Slave是否接收到二进制日志,所以Master与Slave没有任何的依赖关系。异步复制的性能最好,如果业务对于数据一致性要求不高,当发生故障时,能容忍数据的丢失,甚至大量的丢失,推荐用异步复制

安装

拉取MySQL Docker Image

docker pull mysql:8.0.26

获取默认的my.cnf

  • 启动mysql
docker run -d -p 3306:3306 --name mysql-get-conf -e MYSQL_ROOT_PASSWORD="root"  mysql:8.0.26
  • 复制配置文件到本机
docker cp mysql-get-conf:/etc/mysql/my.cnf ./
  • 删除获取配置的容器
docker rm -f mysql-get-conf
  • 复制配置文件
# 根据个人实际情况放置配置文件
mkdir /home/dong/db1 /home/dong/db2
cp my.cnf /home/dong/db1
cp my.cnf /home/dong/db2

启动MySQL容器

  • docker网络配置
# 查看
docker network ls

# 创建
docker network create db-net
  • 启动
docker run --name db1 -v /home/dong/db1/my.cnf:/etc/mysql/my.cnf -e MYSQL_ROOT_PASSWORD=root -d --network db-net mysql:8.0.26
docker run --name db2 -v /home/dong/db2/my.cnf:/etc/mysql/my.cnf -e MYSQL_ROOT_PASSWORD=root -d --network db-net mysql:8.0.26
  • 查看运行状态
dong@DESKTOP:~$ docker ps | grep mysql
84e7e0887bc6        mysql:8.0.26        "docker-entrypoint.s…"   28 seconds ago      Up 27 seconds       3306/tcp, 33060/tcp      db2
c6989e437e61        mysql:8.0.26        "docker-entrypoint.s…"   34 seconds ago      Up 33 seconds       3306/tcp, 33060/tcp      db1
  • 其他命令
# 连接容器数据库
docker exec -it db1 mysql -uroot -proot

# 查看容器目录
docker exec -it db1 ls

修改配置

主服务配置

# vim /home/dong/db1/my.cnf
# 添加下面的配置
server_id = 1  # 在二进制日志时复制模式下要唯一
gtid_mode = ON  # 开启GTID模式
enforce_gtid_consistency = ON  # 强制执行 GTID 一致性
binlog_gtid_simple_recovery = ON # 控制MySQL启动或重新启动时在搜索GTID期间二进制日志文件的重复方式
relay_log_recovery = ON  # 启动时使用中继日志恢复

重启服务

# 重启
docker restart db1
# 查看
docker ps | grep mysql

创建用户,用于同步复制数据

# 登录数据
docker exec -it db1 mysql -uroot -proot

# 注意:这里使用mysql_native_password认证, MySQL8默认认证需要使用SSL, 这里为了方便所以使用mysql_native_password认证
# 创建用户
CREATE USER repl_user@'%' IDENTIFIED WITH mysql_native_password BY 'repl*User123'; 
# 设置权限
Grant replication slave on *.* to 'repl_user'@'%';
# 刷新
flush privileges;

创建测试数据

# 创建数据
CREATE DATABASE `blog` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# 使用表
use blog;

# 创建表
CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

# 插入数据
insert into user (username) values("test1");
insert into user (username) values("test2");

# 查看数据
select * from user;

查看master status

mysql> show master status;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000003 |     2955 |              |                  | 81e99d09-f5f5-11eb-8a5a-0242ac120002:1-11 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

备份主服务器数据

# 登录容器
docker exec -it db1 bash
# 执行导出
mysqldump -uroot -proot --single-transaction --databases blog > /tmp/db.sql
# 复制到本地
docker cp db1:/tmp/db.sql ./

# db.sql说明; 数据库当前gtid是 xxx0002:1-11, 新增的会基本这个后面写入, 保证数据不重复和不丢失, 和上面master status Gtid对应(Gtid操作数据库会变)
SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ '81e99d09-f5f5-11eb-8a5a-0242ac120002:1-11';

从服务器配置

配置

# vim /home/dong/db2/my.cnf
[mysqld]
server_id = 2  # 在二进制日志时复制模式下要唯一
gtid_mode = ON  # 开启GTID模式
enforce_gtid_consistency = ON  # 强制执行 GTID 一致性
binlog_gtid_simple_recovery = ON # 控制MySQL启动或重新启动时在搜索GTID期间二进制日志文件的重复方式
relay_log_recovery = ON  # 启动时使用中继日志恢复

重启

docker restart db2

导入数据

复制数据到容器
docker cp db.sql db2:/tmp

# 登录MySQL
docker exec -it db2 mysql -uroot -proot

# 导入
source /tmp/db.sql

设置同步

# 登录
docker exec -it db2 mysql -uroot -proot

# 设置
mysql> CHANGE MASTER TO MASTER_HOST = 'db1', MASTER_PORT = 3306, MASTER_USER = 'repl_user', MASTER_PASSWORD = 'repl*User123', MASTER_AUTO_POSITION = 1;
Query OK, 0 rows affected, 8 warnings (0.07 sec)

# 启动
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

# 查看状态
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: db1
                  Master_User: repl_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000004
          Read_Master_Log_Pos: 196
               Relay_Log_File: d8a9b6ad089b-relay-bin.000002
                Relay_Log_Pos: 365
        Relay_Master_Log_File: binlog.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 196
              Relay_Log_Space: 581
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: 81e99d09-f5f5-11eb-8a5a-0242ac120002
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set: 81e99d09-f5f5-11eb-8a5a-0242ac120002:1-11
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)

测试

# 登录master
docker exec -it db1 mysql -uroot -proot

# 写入数据
mysql> insert into blog.user (username) values("test3");
Query OK, 1 row affected (0.02 sec)

# 登录slave
docker exec -it db2 mysql -uroot -proot

# 查看数据
mysql> select * from blog.user;
+----+----------+
| id | username |
+----+----------+
|  1 | test1    |
|  2 | test2    |
|  3 | test3    |
+----+----------+
5 rows in set (0.00 sec)

其他常用命令

# 停止slave
stop slave;

# 重设slave
reset slave;

# 重设master
reset master;

# 主服务查看salve
show slave hosts;

# 查点当前连接
show processlist;

# 查看用户信息
select Host, User, plugin from user;

# 查看权限
show grants for repl_user@'%';