这里说几个的半同步复制模式的参数:
mysql> show variables like '%Rpl%'; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_for_slave_count | 1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | | rpl_stop_slave_timeout | 31536000 | +-------------------------------------------+------------+ -- 半同步复制模式开关 rpl_semi_sync_master_enabled -- 半同步复制,超时时间,单位毫秒,当超过此时间后,自动切换为异步复制模式 rpl_semi_sync_master_timeout -- MySQL 5.7.3引入的,该变量设置主需要等待多少个slave应答,才能返回给客户端,默认为1。 rpl_semi_sync_master_wait_for_slave_count -- 此值代表当前集群中的slave数量是否还能够满足当前配置的半同步复制模式,默认为ON,当不满足半同步复制模式后,全部Slave切换到异步复制,此值也会变为OFF rpl_semi_sync_master_wait_no_slave -- 代表半同步复制提交事务的方式,5.7.2之后,默认为AFTER_SYNC rpl_semi_sync_master_wait_point GTID模式MySQL从5.6版本开始推出了GTID复制模式,GTID即全局事务ID (global transaction identifier)的简称,GTID是由UUID+TransactionId组成的,UUID是单个MySQL实例的唯一标识,在第一次启动MySQL实例时会自动生成一个server_uuid, 并且默认写入到数据目录下的auto.cnf(mysql/data/auto.cnf)文件里。TransactionId是该MySQL上执行事务的数量,随着事务数量增加而递增。这样保证了GTID在一组复制中,全局唯一。
这样通过GTID可以清晰的看到,当前事务是从哪个实例上提交的,提交的第多少个事务。
来看一个GTID的具体形式:
mysql> show master status; +-----------+----------+--------------+------------------+-------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-----------+----------+--------------+------------------+-------------------------------------------+ | on.000003 | 187 | | | 76147e28-8086-4f8c-9f98-1cf33d92978d:1-322| +-----------+----------+--------------+------------------+-------------------------------------------+ 1 row in set (0.00 sec)GTID:76147e28-8086-4f8c-9f98-1cf33d92978d:1-322
UUID:76147e28-8086-4f8c-9f98-1cf33d92978d
TransactionId:1-322
由于GTID在一组主从复制集群中的唯一性,从而保证了每个GTID的事务只在一个MySQL上执行一次。
那么是怎么实现这种机制的呢?GTID的原理又是什么样的呢?
当从服务器连接主服务器时,把自己执行过的GTID(Executed_Gtid_Set: 即已经执行的事务编码)以及获取到GTID(Retrieved_Gtid_Set: 即从库已经接收到主库的事务编号)都传给主服务器。主服务器会从服务器缺少的GTID以及对应的transactionID都发送给从服务器,让从服务器补全数据。当主服务器宕机时,会找出同步数据最成功的那台conf服务器,直接将它提升为主服务器。若是强制要求某一台不是同步最成功的一台从服务器为主,会先通过change命令到最成功的那台服务器,将GTID进行补全,然后再把强制要求的那台机器提升为主。
主要数据同步机制可以分为这几步:
master更新数据时,在事务前生产GTID,一同记录到binlog中。
slave端的i/o线程,将变更的binlog写入到relay log中。
sql线程从relay log中获取GTID,然后对比Slave端的binlog是否有记录。
如果有记录,说明该GTID的事务已经执行,slave会忽略该GTID。
如果没有记录,Slave会从relay log中执行该GTID事务,并记录到binlog。
在解析过程中,判断是否有主键,如果没有主键就使用二级索引,再没有二级索引就扫描全表。
初始结构如下图
当Master出现宕机后,就会演变成下图。
通过上图我们可以看出来,当Master挂掉后,Slave-1执行完了Master的事务,Slave-2延时一些,所以没有执行完Master的事务,这个时候提升Slave-1为主,Slave-2连接了新主(Slave-1)后,将最新的GTID传给新主,然后Slave-1就从这个GTID的下一个GTID开始发送事务给Slave-2。这种自我寻找复制位置的模式减少事务丢失的可能性以及故障恢复的时间。 GTID的优劣势
通过上面的分析我们可以得出GTID的优势是:
每一个事务对应一个执行ID,一个GTID在一个服务器上只会执行一次;
GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置;
减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机;
GTID的缺点也很明显:
首先不支持非事务的存储引擎;