GTID
  为了解决这一个问题,MySQL 5.6之后引入了GTID的概念,即uuid:gid,uuid为MySQL server的uuid,是全局的,而gid则是一个递增的事务id,通过这两个东西,我们能标示一个记录到binlog中的事务。使用GTID,我们能非常方便的进行failover的处理。
  仍然是前面的例子,假设b此时读取到的a后一个GTID为3E11FA47-71CA-11E1-9E33-C80AA9429562:23,而c的为3E11FA47-71CA-11E1-9E33-C80AA9429562:15,当c指向新的master b的时候,我们通过GTID可以知道,只要在b中的binlog中找到GTID为3E11FA47-71CA-11E1-9E33-C80AA9429562:15这个event,那么c可以从它的下一个event的位置开始复制了。虽然查找binlog的方式仍然是顺序查找,稍显低效暴力,但比起我们自己去猜测哪一个filename和position,要方便太多了。
  google很早也有了一个Global Transaction ID的补丁,不过只是使用的一个递增的整形,LedisDB借鉴了它的思路来实现failover,只不过google貌似现在也开始逐步迁移到MariaDB上面去了。
  MariaDB的GTID实现跟MySQL 5.6是不一样的,这点其实比较麻烦,对于我的MySQL工具集go-mysql来说,意味着要写两套不同的代码来处理GTID的情况了。后续是否支持MariaDB再看情况吧。
  Pseudo GTID
  GTID虽然是一个好东西,但是于MySQL 5.6+,当前仍然有大部分的业务使用的是5.6之前的版本,笔者的公司是5.5的,而这些数据库至少长时间也不会升级到5.6的。所以我们仍然需要一套好的机制来选择master binlog的filename以及position。
  初,笔者打算研究MHA的实现,它采用的是首先复制relay log来补足缺失的event的方式,但笔者不怎么信任relay log,同时加之MHA采用的是perl,一个让我完全看不懂的语言,所以放弃了继续研究。
  幸运的是,笔者遇到了orchestrator这个项目,这真的是一个非常神奇的项目,它采用了一种Pseudo GTID的方式,核心代码是这个
  create database if not exists meta;
  drop event if exists meta.create_pseudo_gtid_view_event;
  delimiter ;;
  create event if not exists
  meta.create_pseudo_gtid_view_event
  on schedule every 10 second starts current_timestamp
  on completion preserve
  enable
  do
  begin
  set @pseudo_gtid := uuid();
  set @_create_statement := concat('create or replace view meta.pseudo_gtid_view as select /'', @pseudo_gtid, '/' as pseudo_gtid_unique_val from dual');
  PREPARE st FROM @_create_statement;
  EXECUTE st;
  DEALLOCATE PREPARE st;
  end
  ;;
  delimiter ;
  set global event_scheduler := 1;
  它在MySQL上面创建了一个事件,每隔10s,将一个uuid写入到一个view里面,而这个是会记录到binlog中的,虽然我们仍然不能像GTID那样直接定位到一个event,但也能定位到一个10s的区间了,这样我们能在很小的一个区间里面对比两个MySQL的binlog了。
  继续上面的例子,假设c后一次出现uuid的位置为s1,我们在b里面找到该uuid,位置为s2,然后依次对比后续的event,如果不一致,则可能出现了问题,停止复制。当遍历到c后一个binlog event之后,我们能得到此时b下一个event对应的filename以及position了,然后让c指向这个位置开始复制。
  使用Pseudo GTID需要slave打开log-slave-update的选项,考虑到GTID也必须打开该选项,所以个人感觉完全可以接受。
  后续,笔者自己实现的failover工具,将会采用这种Pseudo GTID的方式实现。
  在《MySQL High Availability》这本书中,作者使用了另一种GTID的做法,每次commit的时候,需要在一个表里面记录gtid,然后通过这个gtid来找到对应的位置信息,只是这种方式需要业务MySQL客户端的支持,笔者不很喜欢,不采用了。