MySQL 基于GTID复制
GTID Replication:
在MySQL 5.6.5以上的版本中,MySQL新增了一种基于GTID的复制方式。通过 GTID 保证了每个在主数据库上提交的事务在集群中有一个唯一的ID,这种方式强化了数据库主备的一致性,故障恢复以及容错能力。
GTID是什么?:
GTID (Global Transaction ID) 是对一个已提交事务的编号,并且是一个全局唯一的编号。GTID 是由 UUID+TID 组成的。UUID 是一个 MySQL 实例的唯一标识,TID 代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。
UUID是什么?
MySQL 5.6 以后用 128 位的 server-uuid 代替了原本的 32 位 server-id。server-id 是基于 my.cnf 的手工配置,易产生冲突,而UUID可以保证所生成的 server-uuid 避免冲突问题。
查看UUID:
show variables like "%server_uuid%";
3ff69404-0b11-11e8-a5c9-000c29713b71
查看GTID:
3ff69404-0b11-11e8-a5c9-000c29713b71:1
GTID形式:
3ff69404-0b11-11e8-a5c9-000c29713b71:1
3ff69404-0b11-11e8-a5c9-000c29713b71:5 #一组连续的事物
GTID复制实现的工作原理
- master更新数据时,会在事务前产生GTID,一同记录到binlog日志中;
- slave的 IO thread 将变更的binlog,写入到本地的 relay log 中;
- SQL thread 从 relay log 中获取GTID,然后对比 slave 的 binlog 是否有记录;
- 如果有记录,说明该GTID的事务已经执行,slave 会忽略;
- 如果没有记录,slave就会从 relay log 中执行该GTID的事务,并记录到 binlog ;
- 在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
show binlog events in 'mysql-bin.000003';
| mysql-bin.000003 | 2152 | Gtid | 1283306 | 2217 | SET @@SESSION.GTID_NEXT= '3ff69404-0b11-11e8-a5c9-000c29713b71:12' |
| mysql-bin.000003 | 2217 | Query | 1283306 | 2290 | BEGIN |
| mysql-bin.000003 | 2290 | Table_map | 1283306 | 2339 | table_id: 145 (gtidb.gtitb) |
| mysql-bin.000003 | 2339 | Write_rows | 1283306 | 2379 | table_id: 145 flags: STMT_END_F |
| mysql-bin.000003 | 2379 | Xid | 1283306 | 2410 | COMMIT /* xid=588 */ |
配置GTID主从复制:
master配置:
- gtid-mode:gtid-mode=ON
- enforce-gtid-consistency:enforce-gtid-consistency=ON
- log-slave-updates:log-slave-updates:ON
- server-id 1003306,(建议IP后两位加数据库端口号)
- binlog_format:binlog_format=ROW
- log-bin:log-bi=ON
创建复制账号:
grant replication slave on *.* to 'repl'@'%' identified by 'password';
flush privileges;
查看master状态:
show master status\G;
slave配置:
- gtid-mode:gtid-mode=ON
- enforce-gtid-consistency:enforce-gtid-consistency=ON
- log-slave-updates:log-slave-updates:ON
- server-id 1013306,(建议IP后两位加数据库端口号)
- binlog_format:binlog_format=ROW
- log-bin:log-bi=ON
连接主数据:
连接主库:
CHANGE MASTER TO
MASTER_HOST='192.168.100.100',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1;
开开启同步:
start slave;
查看slave状态:
show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Retrieved_Gtid_Set: 3ff69404-0b11-11e8-a5c9-000c29713b71:1-3
Executed_Gtid_Set: 3ff69404-0b11-11e8-a5c9-000c29713b71:1-3
GTID相关参数:
show global variables like '%gtid%';
show variables like '%gtid_next%';
gtid_executed:在当前实例上执行过的GTID集合; 实际上包含了所有记录到binlog中的事务。所以,设置set sql_log_bin=0后执行的事务不会生成binlog 事件,也不会被记录到gtid_executed中。执行RESET MASTER可以将该变量置空。
gtid_purged:binlog不可能永远驻留在服务上,需要定期进行清理(通过expire_logs_days可以控制定期清理间隔),否则迟早它会把磁盘用尽。gtid_purged用于记录已经被清除了的binlog事务集合,它是gtid_executed的子集。只有gtid_executed为空时才能手动设置该变量,此时会同时更新gtid_executed为和gtid_purged相同的值。gtid_executed为空意味着要么之前没有启动过基于GTID的复制,要么执行过RESET MASTER。执行RESET MASTER时同样也会把gtid_purged置空,即始终保持gtid_purged是gtid_executed的子集。
gtid_next:话级变量,指示如何产生下一个GTID。
- AUTOMATIC:自动生成下一个GTID,实现上是分配一个当前实例上尚未执行过的序号最小的GTID。
- ANONYMOUS:设置后执行事务不会产生GTID。
- 显式指定的GTID:可以指定任意形式合法的GTID值,但不能是当前gtid_executed中的已经包含的GTID,否则,下次执行事务时会报错。