GTID实现主从复制数据同步

GTID是一个基于原始mysql服务器生成的一个已经被成功执行的全局事务ID,它由服务器ID以及事务ID组成,这个全局事务ID不仅仅在原始服务器上唯一,在所有主从关系的mysql服务器上也是唯一的。正式因为这样一个特性使得mysql主从复制变得更加简单,以及数据库一致性更可靠。

介绍

GTID的概念

  1. 全局事务标识:global transaction identifiers
  2. GTID是一个事务一一对应,并且全局唯一ID
  3. 一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱不一致
  4. 不再使用传统的MASTER_LOG_FILE+MASTER_LOG_POS开启复制,而是采用MASTER_AUTO_POSTION=1的方式开启复制。
  5. 从MYSQL-5.6.5及后续版本开始支持

GTID的组成

GTID = server_uuid:transaction_id

server_uuid:mysql服务器的唯一标识,查看方法mysql客户端内:show variables like '%server_uuid%';

transaction_id:此id是当前服务器中提交事务的一个序列号,从1开始自增长,一个数值对应一个事务

GTID号示例:c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-5

GTID的优势

  1. 实现主从更简单,不用像以前一样寻找log_file和log_pos
  2. 比传统的主从更加安全
  3. GTID是连续没有空洞的,保证数据一致性,零丢失。

GTID工作原理

  1. 当一个事务在主库端执行并提交时,产生GTID,并一同记录到binlog日志中;
  2. binlog传输到slave,并存储到slave的relaylog后,读取这个GTID的

开始配置GTID复制

主:192.168.152.253   Centos7

从:192.168.152.252   Centos8

测试数据库:vfan

测试表:student

1、修改mysql服务配置文件,添加以下参数,随后重启:

server-id=100    #server id
log-bin=/var/lib/mysql/mysql-bin #开启binlog并指定存储位置
expire_logs_days=10 #日志保存时间为10天
gtid_mode=on #gtid模块开关
enforce_gtid_consistency=on #启动GTID强一致性,开启gtid模块必须开启此功能。
binlog_format=row #bin_log日志格式,共有三种STATEMENT、ROW、MIXED;默认为STATEMENT
skip_slave_start=1 #防止复制随着mysql启动而自动启动

主服务器和从服务器的配置一致即可,server-id更改一下

2、在主服务器中创建从服务器连接的用户

CREATE USER 'copy'@'192.168.152.252' IDENTIFIED BY 'copy';
GRANT REPLICATION SLAVE ON *.* TO 'copy'@'192.168.152.252';
flush privileges;

创建完毕记得要测试下slave机是否能登录成功

3、使用mysqldump使两数据库数据同步

主mysql执行:
mysqldump -uroot -proot1 vfan > dump2.sql
scp dump2.sql 192.168.152.252:/data/ 从mysql执行:
mysql> source /data/dump2.sql

当前主、从服务器数据内容一致,都是以下数据:

mysql> select * from student;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | Tony | 18 |
| 2 | Any | 17 |
| 3 | Goy | 20 |
| 4 | Baly | 18 |
| 5 | Heg | 19 |
| 6 | hhh | 100 |
| 7 | lll | 99 |
+----+------+-----+
7 rows in set (0.01 sec)

4、开启主从复制

mysql> CHANGE MASTER TO MASTER_HOST='192.168.152.253',MASTER_USER='copy',MASTER_PASSWORD='copy',MASTER_PORT=3306,MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.04 sec) mysql> start slave;
Query OK, 0 rows affected (0.01 sec) ## 查看slave状态
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.152.253
Master_User: copy
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000014
Read_Master_Log_Pos: 897
Relay_Log_File: kubenode2-relay-bin.000002
Relay_Log_Pos: 416
Relay_Master_Log_File: mysql-bin.000014
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

5、检查是否同步

主服务器中插入数据:
mysql> INSERT INTO student(name,age) VALUES('gogoo',50),('zhazha',25);
Query OK, 2 rows affected (0.03 sec)
Records: 2 Duplicates: 0 Warnings: 0 从服务器中读取:
mysql> select * from student;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | Tony | 18 |
| 2 | Any | 17 |
| 3 | Goy | 20 |
| 4 | Baly | 18 |
| 5 | Heg | 19 |
| 6 | hhh | 100 |
| 7 | lll | 99 |
| 8 | gogoo | 50 |
| 9 | zhazha | 25 |
+----+--------+-----+
9 rows in set (0.00 sec)

数据已经同步,基础的主从复制已经搭建完成

现在模拟一个主从复制架构中,从服务器中途复制失败,不再同步主服务器的场景,并要求不停业务进行数据同步修复,恢复一致。

1、首先先模拟一个数据插入的场景

vim insert.sh

#!/usr/bin/env bash

values=(`find /usr/ -type d | awk -F '/' '{print $NF}' | sort -u`)

while true
do
age=$(( $RANDOM%100 ))
name=${values[$(( $RANDOM%6 ))]} mysql -h127.1 -P3306 -uroot -proot1 -e "INSERT INTO vfan.student(name,age) VALUES('"${name}"',${age});" &> /dev/null
sleep $(( $RANDOM%5 ))
done

运行脚本,数据在随机插入(插入时间间隔 < 5s)

目前主mysql数据:

mysql> select * from student;
+----+---------------------+-----+
| id | name | age |
......
| 97 | _ | 2 |
| 98 | 00bash | 15 |
| 99 | 00bash | 52 |
| 100 | 00bash | 43 |
| 101 | _ | 65 |
| 102 | 00 | 67 |
+-----+---------------------+-----+
102 rows in set (0.01 sec)

2、数据还在陆续插入,此时模拟slave节点宕机或异常(在此就直接stop slave;)

mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

3、此时主库数据还在增加,而从库已经不同步,以下是从库数据:

mysql> select * from student;
+----+---------------------+-----+
| id | name | age |
......
| 82 | 00bash | 50 |
| 83 | 00systemd-bootchart | 36 |
| 84 | 00bash | 48 |
| 85 | 00systemd-bootchart | 41 |
| 86 | 00 | 72 |
+----+---------------------+-----+
86 rows in set (0.00 sec)

4、开始从库恢复数据

思路:

先通过mysqldump全量备份当前的数据,由于不能影响业务,所以在mysqldump数据时不能造成锁表。要保持数据写入

由于mysqldump时数据还在写入,所以有一部分数据还是会同步不全,所以导入mysqldump的数据后,跳过dump中包含的GTID事务,再重新建立一次主从配置,开启slave线程,恢复数据并同步。

(1)mysqldump不锁表备份数据

mysqldump -uroot -proot1 --single-transaction --master-data=2 -R vfan | gzip > dump4.sql

主要起作用参数:--single-transaction

(2)查看当前mysqldump导出数据的GTID号

[root@TestCentos7 data]# grep GLOBAL.GTID_PURGED dump4.sql
SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ 'c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228';

以上的 c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228 表示MASTER机执行到的GTID事务号

(3)去从数据库导入

scp dump4.sql 192.168.152.252:/data

mysql客户端内:
mysql> source /data/dump4.sql 此时从库数据:
mysql> select * from student;
| 230 | 00 | 53 |
| 231 | 00bash | 66 |
| 232 | _ | 18 |
| 233 | 0.33.0 | 98 |
| 234 | 00bash | 14 |
+-----+---------------------+-----+
234 rows in set (0.00 sec) 主库数据:
| 454 | _ | 46 |
| 455 | 03modsign | 59 |
| 456 | 00systemd-bootchart | 77 |
| 457 | 03modsign | 6 |
| 458 | 0.33.0 | 88 |
+-----+---------------------+-----+
458 rows in set (0.00 sec)

从库数据恢复一部分到234行,主库数据依然在增加,已经是458条

(4)由于我们mysqldump的数据已经包含了在MASTER执行的 1-228 个事务,所以我们在SLAVE进行同步的时候,要忽略这些事务不再进行同步,不然会出现类似于这种报错:

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.152.253
Master_User: copy
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 137827
Relay_Log_File: kubenode2-relay-bin.000002
Relay_Log_Pos: 417
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table vfan.student; Duplicate entry '87' for key 'student.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000002, end_log_pos 10588

要想跳过某些GTID,SLAVE必须保证 gtid_purged 参数为空才能正确跳过,查看当前的gtid_purged:

mysql> show global variables like '%gtid%';
+----------------------------------+-------------------------------------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+-------------------------------------------------------------------------------------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed | b30cb2ff-32d4-11eb-a447-000c292826bc:1-2,
c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-80 |
| gtid_executed_compression_period | 1000 |
| gtid_mode | ON |
| gtid_owned | |
| gtid_purged | c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-70 |
| session_track_gtids | OFF |
+----------------------------------+-------------------------------------------------------------------------------------+
8 rows in set (0.02 sec)

当前gtid_purged不为空,所以我们要先设置它为空,执行:

mysql> reset master;
Query OK, 0 rows affected (0.05 sec) mysql> show global variables like '%gtid%';
+----------------------------------+-------+
| Variable_name | Value |
+----------------------------------+-------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed | |
| gtid_executed_compression_period | 1000 |
| gtid_mode | ON |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+-------+
8 rows in set (0.00 sec)

(5)gtid_purged为空后,开始重置SLAVE

mysql> stop slave;
Query OK, 0 rows affected (0.00 sec) mysql> reset slave all;
Query OK, 0 rows affected (0.02 sec)

(6)重置后,设置跳过的GTID,并重新同步MASTER

mysql> SET @@GLOBAL.GTID_PURGED='c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228';
Query OK, 0 rows affected (0.01 sec) mysql> CHANGE MASTER TO MASTER_HOST='192.168.152.253',MASTER_USER='copy',MASTER_PASSWORD='copy',MASTER_PORT=3306,MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.04 sec)

(7)开启SLAVE进程,查看同步状态

mysql> start slave;
Query OK, 0 rows affected (0.01 sec) mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.152.253
Master_User: copy
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 137827
Relay_Log_File: kubenode2-relay-bin.000002
Relay_Log_Pos: 84993
Relay_Master_Log_File: mysql-bin.000002
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: 137827
Relay_Log_Space: 85206
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: 100
Master_UUID: c9fba9e2-db3b-11eb-81d4-000c298d8da1
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave 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: c9fba9e2-db3b-11eb-81d4-000c298d8da1:229-519
Executed_Gtid_Set: c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-519
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 (0.00 sec)

可以看到,同步正常!

(8)最后,查看master与slave数据是否一致

MASTER数据:SELECT * FROM student;
| 520 | 00systemd-bootchart | 18 |
| 521 | 00systemd-bootchart | 44 |
| 522 | 03modsign | 98 |
| 523 | 00systemd-bootchart | 45 |
| 524 | 00 | 90 |
| 525 | 03modsign | 21 |
+-----+---------------------+-----+
525 rows in set (0.00 sec) SLAVE数据:SELECT * FROM student;
| 519 | 0.33.0 | 99 |
| 520 | 00systemd-bootchart | 18 |
| 521 | 00systemd-bootchart | 44 |
| 522 | 03modsign | 98 |
| 523 | 00systemd-bootchart | 45 |
| 524 | 00 | 90 |
| 525 | 03modsign | 21 |
+-----+---------------------+-----+
525 rows in set (0.00 sec)

在我们修过程中插入的数据也已经全部同步。数据完全一致,主从复制修复完成。

mysql GTID主从复制故障后不停机恢复同步流程的更多相关文章

  1. MySQL误操作删除后,怎么恢复数据?

    MySQL误操作删除后,怎么恢复数据?登陆查数据库mysql> select * from abc.stad;+----+-----------+| id | name |+----+----- ...

  2. mysql gtid 主从复制

    基于GTID环境搭建主从复制 1.环境 ----------------------------------------------------------| |mysql版本 | 5.7.14 | ...

  3. MySQL GTID 主从复制错误修复方法

    https://yq.aliyun.com/articles/155827?spm=5176.8067842.tagmain.6.RFPTAL MySQL 传统的主从复制方式使用 master_log ...

  4. Redis源码解析:17Resis主从复制之主节点的部分重同步流程及其他

    本文主要讲解主节点部分重同步的实现,以及主从复制中的其他功能.本文是Redis主从复制机制的最后一篇文章. 主节点在收到从节点发来的PSYNC命令之前,主节点的部分重同步流程,与完全重同步流程是一样的 ...

  5. Redis源码解析:16Resis主从复制之主节点的完全重同步流程

    主从复制过程中,主节点根据从节点发来的命令执行相应的操作.结合上一章中讲解的从节点在主从复制中的流程,本章以及下一篇文章讲解一下主节点在主从复制过程中的流程. 本章主要介绍完全重同步流程. 一:从节点 ...

  6. mysql GTID主从复制(主库在线,添加新丛库)

    要求: 1.         主库上线,主库不停止服务的前提下做主从复制 2.         新添加一个丛库 操作: 1.         在主库导出数据(主库正常运行): 2.         将 ...

  7. MySQL GTID 错误处理汇总

    MySQL GTID是在传统的mysql主从复制的基础之上演化而来的产物,即通过UUID加上事务ID的方式来确保每一个事物的唯一性.这样的操作方式使得我们不再需要关心所谓的log_file和log_P ...

  8. MySQL 5.7 基于GTID主从复制+并行复制+半同步复制

    环境准备 IP HOSTNAME SERVICE SYSTEM 192.168.131.129 mysql-master1 mysql CentOS7.6 192.168.131.130 mysql- ...

  9. 解决mysql使用GTID主从复制错误问题

    做MySQL主从的话肯定会遇到很多同步上的问题,大多数都是由于机器宕机,重启,或者是主键冲突等引起的从服务器停止工作,这里专门收集类似问题并提供整理解决方案,仅供参考. 1.主从网络中断,或主服务器重 ...

随机推荐

  1. 20202405李昕亮《BASE64编码》

    BASE64编码 20202405李昕亮 参考网址: 1.https://baike.baidu.com/item/base64/8545775?fr=aladdin 2.https://blog.c ...

  2. Luogu P2447 [SDOI2010]外星千足虫

    题意 给定 \(n\) 个变量和 \(m\) 个异或方程,求最少需要多少个才能确定每个变量的解. \(\texttt{Data Range:}1\leq n\leq 10^3,1\leq m\leq ...

  3. [Luogu P3959] 宝藏 (状压DP+枚举子集)

    题面 传送门:https://www.luogu.org/problemnew/show/P3959 Solution 这道题的是一道很巧妙的状压DP题. 首先,看到数据范围,应该状压DP没错了. 根 ...

  4. 对比JAVA、Python、C、Go运行时间,我惊呆了!!!

    对比JAVA.Python.C.Go运行时间,我惊呆了!!! 周末在寝室刷完算法,想放松一下,于是做了一个实验:用现在主流的几种编程语言对0 - (10000000 - 1)求和,结果我惊呆了,话不多 ...

  5. SVG--D3--血缘关系树

    最近的工作与可视化有关,有展示血缘关系树的需求 ,类似于这样: 碰巧搜到 D3(用于可视化的js库,作者吕之华),瞬间无法自拔,它的树状图功能基于SVG.js ,暴露的可操作入口也简洁恰当,能帮助你快 ...

  6. JavaSE基础语法学习-流程控制

    流程控制 用户交互Scanner Scanner**对象** 下面是创建 Scanner 对象的基本语法: Scanner s = new Scanner(System.in); 接下来我们演示一个最 ...

  7. ElementUI表格行编辑单元格编辑支持(输入框,选择框)Demo

    嗯,需要做成这个样子,所以网上查了些资料.整理了下.提供几个一个思路.不足之处请小伙伴指出来.  普通版的table可编辑内嵌select选择框,输出框,编辑删除添加等 <!DOCTYPE ht ...

  8. cookie的简单介绍

    思考: HTTP是一个无状态的协议,当一个客户端向服务端发送请求,在服务器返回响应后,连接就关闭了,在服务器端不保留连接信息. 当客户端发送多次请求且需要相同的请求参数的时候,应该如何处理?这个时候就 ...

  9. offsetWidth与offsetHeight

    HTMLElement.offsetWidth 是一个只读属性,返回一个元素的布局宽度.一个典型的(译者注:各浏览器的offsetWidth可能有所不同)offsetWidth是测量包含元素的边框(b ...

  10. Jmeter 处理接口乱码

    第一步:添加 BeanShell Listener 第二步: 设置值 : prev.setDataEncoding("UTF-8") 第三步: 重新跑脚本,看接口返回值