MySQL之GTID复制

MySQL之GTID复制

mysql事务

为什么数据库需要事务?

  • 你表弟向你借500元,你打开APP、爽快的给他转账了,你的卡余额提示少了500
  • 你给表弟发了个微信,说,钱打过去了
  • 你表弟说:没收到啊哥,你别骗我行吗
  • 你钱扣少了,你表弟缺没收到钱,这事办的?咋整

讲道理应该是这样

  1. 超哥发起转账,转给表弟
  2. 超哥卡里少了500元
  3. 表弟卡里多了500元

这三步骤、必然不得出问题,上面的案例,就是这三步发生了问题!

如果有事务、就不会发生这样的事

事务就是

这三件事、三个动作,是一根绳上的蚂蚱,要么都成功,要么都失败

转账要么到表弟账户、要么就转不出去、回到自己卡里

事务的ACID特性

TRANSACTION 事务

Atomicity原子性

原子性强调转账的三个步骤要么成功、要么失败

在一个事务中的所有SQL语句,要么全部执行成功,要么全部失败,即使成功的SQL语句也会被撤销,回到执行之前的状态。

Consistency一致性

一致性是指数据库从一个状态、变为另一个状态

事务开始前、与结束后,数据库的完整性约束没有被破坏。

例如转账,无论成功、或者失败、这500不会多、也不会少

要么超哥卡里扣了500元、表弟多了500元

要么超哥转账失败500元未动、表弟一毛钱也没拿到

这个总和永远是500元,不多也不少

Isolation隔离性

隔离性指的是每个读写事务对其他的事务操作,都是相互隔离不受影响的。

例如同是工商银行

  • 超哥转账操作不会影响到小猪佩奇的转账操作

Durability持久性

事务一旦提交后,结果就是永久性生效。

超哥转账500给了表弟,表弟也收到钱了,这件事就结束了,真实生效了。

事务的实现

image-20210426155956492

更多高级mysql知识,超哥后期会再补充

GTID是什么

从 MySQL 5.6.5 开始新增了一种基于 GTID 的复制方式。

通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。

这种方式强化了数据库的主备一致性,故障恢复以及容错能力。

在原来基于二进制日志的复制中,从库需要告知主库要从哪个偏移量进行增量同步,如果指定错误会造成数据的遗漏,从而造成数据的不一致。

借助GTID,在发生主备切换的情况下,MySQL的其它从库可以自动在新主库上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制位置发生误操作的风险。

另外,基于GTID的复制可以忽略已经执行过的事务,减少了数据发生不一致的风险。

GTID长啥样

GTID (Global Transaction ID) 是对于一个已提交事务的编号,并且是一个全局唯一的编号。

GTID 实际上 是由 UUID+TID 组成的。

其中 UUID 是一个 MySQL 实例的唯一标识。

TID 代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。下面是一个GTID的具体形式:

形式语法  
GTID = source_id :transaction_id

具体结果
2E11FA47-61CA-11E1-9E33-C70AA9429562:28

在上面的定义中,每一个GTID均代表一个数据库的事务,等号右边的source_id表示执行事务的源服务器主库的uuid(也就是server_uuid)

而transaction_id是一个从1开始的自增的序列号,表示在这个主库上执行的第n个事务。

只要保证每台数据库的server_uuid全局唯一,以及每台数据库生成的transaction_id自身唯一,就能保证GTID的全局唯一性。

server_uuid是什么

还记得以前我们在my.cnf中配置了一个参数

server_id=5

并且超哥要求master、slave的server_id必须唯一

为什么换成server_uuid

MySQL 5.6用128位的server_uuid代替了原本32位的server_id的大部分功能。

原因很简单,server_id依赖于my.cnf的手工配置,有可能会产生冲突,而自动产生128位uuid的算法可以保证所有的MySQL uuid都不会发生冲突。

在进行首次启动时,MySQL会自动生成一个server_uuid,并且保存到数据库目录下的auto.cnf文件里,这个文件目前存在的唯一目的就是保存server_uuid。

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

使用GTID

GTID复制原理流程

  • master进行数据更新时、在事务前产生GTID号、一起记录到binlog日志。

  • slave的I/O线程将变更的binlog数据,写入到本地中继日志relay_log

  • slave的SQL线程从中继日志中获取

    GTID
    

    号,和本地的binlog对比查看是否有记录

    • 有记录,说明该GTID事务已执行,slave数据库会忽略
  • 如果没有记录,slave数据库从relay_log中继日志中获取数据,且执行该GTID的事务,记录到binlog中

根据GTID号就可以知道事务最初是在哪个数据库上提交的

有了GTID号、可以方便主从复制的故障切换

主从故障切换

如图、在没有GTID以前,主从复制的故障切换

image-20210426111502204

  • master-A宕机,需要将应用程序切换到master-B
  • slave-C得和master-B建立新的复制关系

只需要在slave-C上执行新的change master to xxx ,指定master-B即可

问题是,同一个事务、在每台服务器上的binlog名字和位置点、可能都是不一样的

比如执行一条SQL,创建了一个新数据库,执行了一个事务,在master-A机器的binlog中数据位置如下

mysql> show master status
    -> ;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |     557 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

但是可能在机器master-B中的bin中,同一个SQL执行后,binlog数据位置可能是

mysql> show master status
    -> ;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值