当前位置: 代码迷 >> 综合 >> 深入了解复制-全局事务标识符(GTID)
  详细解决方案

深入了解复制-全局事务标识符(GTID)

热度:46   发布时间:2023-09-27 10:59:11.0

1)什么是GTID

GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识,保存在mysql数据目录下的auto.cnf文件里。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。下面是一个GTID的具体形式:3E11FA47-71CA-11E1-9E33-C80AA9429562:23。

2)GTID的作用

根据GTID可以知道事务最初是在哪个实例上提交的

GTID的存在方便了Replication的Failover

3)GTID比传统复制的优势

更简单的实现failover,不用以前那样在需要找log_file和log_Pos。

更简单的搭建主从复制。

比传统复制更加安全。

GTID是连续没有空洞的,因此主从库出现数据冲突时,可以用添加空事物的方式进行跳过。

4)GTID的工作原理:

master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。

slave端的i/o线程将变更的binlog,写入到本地的relay log中。

sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。

如果有记录,说明该GTID的事务已经执行,slave会忽略。

如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。

在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

5)GTID常用参数注释:

GTID的参数注释:

[master]>showglobal variables like '%gtid%';

enforce_gtid_consistency:开启gtid的一些安全限制(介意开启)。

gtid_executed:全局和seeeion级别都可以用。用来保存已经执行过的GTIDs。

注:showmaster status\G;输出结果中的Executed_Gtid_Set和gitd_executed一致。reset

master时,此值会被清空。

gtid_owned:全局和session级别都可用,全局表示所有服务器拥有GTIDs,session级别表示当前client拥有所有GTIDs。(此功能用的少)

gtid_mode:是否开启GTID功能。

gtid_purged:全局参数,设置在binlog中,已经purged的GTIDs,并且purged掉的GTIDs会包含到gtid_executed中。

注:从而导致slave不会再去master请求这些GTIDs,并且Executed_Gtid_Set为空时,才可以设置此值。

gtid_next:这个时session级别的参数:

6)使用GTID配置主从复制

实际工作主要会在两种情况下配置:一是新搭建的服务器,直接配置启动就可以,二是已经在运行的服务器,这时候需要闭关master的写,保证所有slave端都已经和master端数据保持同步。然后即可按如下方法配置

主服务器配置:

停止mysql服务,修改/etc/my.cnf配置文件,主要配置以下几项:

log-bin =mysql-bin

log_bin_index =mysql-bin.index

expire_logs_days = 30

binlog_format = ROW

log-slave-updates = true

sync-binlog = 1:

gtid-mode = on

enforce-gtid-consistency = true   #强制执行GTID

启动数据库服务,查看相关信息

使用如下命令查看GTID的相关参数:showglobal variables like '%gtid%';

 

深入了解复制-全局事务标识符(GTID)

下图显示GTID是否正常使用:

 

深入了解复制-全局事务标识符(GTID)

再次使用show global variables like '%gtid%';查看参数设置,出现如下结果。

 

深入了解复制-全局事务标识符(GTID)

配置从服务器:

停止mysql服务,修改/etc/my.cnf配置文件,主要配置以下几项:

gtid-mode = on

enforce-gtid-consistency = true

server-id = 1

log-bin =mysql-bin

log_bin_index =mysql-bin.index

expire_logs_days = 30

binlog_format = ROW

sync-binlog = 1:

replicate-do-db=dbname  #指定库

replicate-do-table=dbname.tabname  #指定表,如需多个,则添加多一行

PS:个人测试了指定库参数没有效果,待验证

skip-slave-start   #防止主库重启从库跟着重启

 

以下参数待研究:

elay-log = relay-log  

relay-log-index = relay-log.index 

log-slave-updates = true

master-info-repository = table

relay-log-info-repository = table

slave-parallel-workers = 1

relay_log_purge = 1

relay_log_recovery = 1

report-port = 3306

report-host = 192.168.10.72

 

启动数据库服务

连接master:

CHANGE MASTER TOMASTER_HOST='192.168.10.71',MASTER_PORT=3306,MASTER_USER='repl_user',MASTER_PASSWORD='123456', MASTER_AUTO_POSITION=1;

启动复制线程:

start slave;

相看相关状态:

slave上显示:

mysql> show slave status\G;

*************************** 1. row***************************

Slave_IO_State: Waiting for master to send event

Master_Host: 192.168.10.71

Master_User: repl_user

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: master-bin.000008

Read_Master_Log_Pos: 191

Relay_Log_File: relay-log.000005

Relay_Log_Pos: 363

Relay_Master_Log_File: master-bin.000008

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: 191

Relay_Log_Space: 530

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: 171

Master_UUID:0e9896a7-14f7-11e7-a0e6-000c2900551e

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 the slaveI/O thread to update it

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: 0e9896a7-14f7-11e7-a0e6-000c2900551e:1

Auto_Position: 1

1 row in set (0.00 sec)

在master显示:

 

深入了解复制-全局事务标识符(GTID)

7)、修复GTID复制错误

在基于GTID的复制拓扑中,要想修复Slave的SQL线程错误,过去的SQL_SLAVE_SKIP_COUNTER方式不再适用。需要通过设置gtid_next或gtid_purged完成,当然前提是已经确保主从数据一致,仅仅需要跳过复制错误让复制继续下去。其中gtid_next就是跳过某个执行事务,设置gtid_next的方法一次只能跳过一个事务,要批量的跳过事务可以通过设置gtid_purged完成。

PS:跳过错误步骤:

stop slave;

setgtid_next='xxxxxxxx:n';

begin;

commit;

setgtid_next='automatic';

start slave;

8)、一主多从架构报错:A slave with the same server_uuid as this slave has connected to the master; the first event

意思就是存在相同server_uuid的从服务器,网上比较好的解释如下:

  1. MySQL 5.6 用 128 位的 server_uuid 代替了原本的 32 位 server_id 的大部分功能。原因很简单,server_id 依赖于 my.cnf 的手工配置,有可能产生冲突 —— 而自动产生 128 位 uuid 的算法可以保证所有的 MySQL uuid 都不会冲突。

  2. 在首次启动时 MySQL 会调用 generate_server_uuid() 自动生成一个 server_uuid,并且保存到 auto.cnf 文件 —— 这个文件目前存在的唯一目的就是保存 server_uuid。

  3. 在 MySQL 再次启动时会读取 auto.cnf 文件,继续使用上次生成的 server_uuid。

  4. 使用 SHOW 命令可以查看 MySQL 实例当前使用的 server_uuid?:

  5. SHOW GLOBAL VARIABLES LIKE 'server_uuid';

  6. 它是一个 MySQL 5.6 global variables

  7. 全局唯一的 server_uuid 的一个好处是:可以解决由 server_id 配置冲突带来的 MySQL 主备复制的异常终止

  8. 在 MySQL 5.6,Slave 向 Master 申请 binlog 时,会首先发送自己的 server_uuid,Master 用 Slave 发送的 server_uuid 代替 server_id (MySQL 5.6 之前的方式)作为 kill_zombie_dump_threads 的参数,终止冲突或者僵死的 BINLOG_DUMP 线程。

我的解决方法是:vim $MYSQL_HOME/data/auto.cnf,把server_uuid随便更改为格式相同的另一值



参考链接:

https://www.jianshu.com/p/ea9fdcc25378

https://blog.csdn.net/dba_waterbin/article/details/27533869