http://mysql.taobao.org/monthly/2016/08/01/php
https://www.kancloud.cn/thinkphp/mysql-parallel-applier/45909mysql
5.7新版本复制方面的主要优化内容:sql
运维thinkphp
新特性服务器
性能网络
logical_clock方便的内容:并发
MySQL 5.7才可称为真正的并行复制,这其中最为主要的缘由就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。再也不有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。app
从MySQL官方来看,其并行复制的本来计划是支持表级的并行复制和行级的并行复制,行级的并行复制经过解析ROW格式的二进制日志的方式来完成,WL#4648。可是最终出现给小伙伴的确是在开发计划中称为:MTS: Prepared transactions slave parallel applier,可见:WL#6314。该并行复制的思想最先是由MariaDB的Kristain提出,并已在MariaDB 10中出现,相信不少选择MariaDB的小伙伴最为看重的功能之一就是并行复制。less
MySQL 5.7并行复制的思想简单易懂,一言以蔽之:一个组提交的事务都是能够并行回放,由于这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(不然就不可能提交)。运维
为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其能够配置的值有:
如何知道事务是否在一组中,又是一个问题,由于原版的MySQL并无提供这样的信息。在MySQL 5.7版本中,其设计方式是将组提交的信息存放在GTID中。那么若是用户没有开启GTID功能,即将参数gtid_mode设置为OFF呢?故MySQL 5.7又引入了称之为Anonymous_Gtid的二进制日志event类型,如:
mysql> SHOW BINLOG EVENTS in 'mysql-bin.000006'; +------------------+-----+----------------+-----------+-------------+-----------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+----------------+-----------+-------------+-----------------------------------------------+ | mysql-bin.000006 | 4 | Format_desc | 88 | 123 | Server ver: 5.7.7-rc-debug-log, Binlog ver: 4 | | mysql-bin.000006 | 123 | Previous_gtids | 88 | 194 | f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2 | | mysql-bin.000006 | 194 | Anonymous_Gtid | 88 | 259 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | mysql-bin.000006 | 259 | Query | 88 | 330 | BEGIN | | mysql-bin.000006 | 330 | Table_map | 88 | 373 | table_id: 108 (aaa.t) | | mysql-bin.000006 | 373 | Write_rows | 88 | 413 | table_id: 108 flags: STMT_END_F | ......
这意味着在MySQL 5.7版本中即便不开启GTID,每一个事务开始前也是会存在一个Anonymous_Gtid,而这GTID中就存在着组提交的信息。
然而,经过上述的SHOW BINLOG EVENTS,咱们并无发现有关组提交的任何信息。可是经过mysqlbinlog工具,用户就能发现组提交的内部信息:
root@localhost:~# mysqlbinlog mysql-bin.0000006 | grep last_committed #150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1 #150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2 #150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3 #150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4 #150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5 #150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6 #150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7 #150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8 #150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9 #150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10 #150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11 #150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12 #150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13 ...
能够发现较之原来的二进制日志内容多了last_committed和sequence_number,last_committed表示事务提交的时候,上次事务提交的编号,若是事务具备相同的last_committed,表示这些事务都在一组内,能够进行并行的回放。例如上述last_committed为0的事务有6个,表示组提交时提交了6个事务,而这6个事务在从机是能够进行并行回放的。
上述的last_committed和sequence_number表明的就是所谓的LOGICAL_CLOCK。先来看源码中对于LOGICAL_CLOCK的定义:
class Logical_clock { private: int64 state; /* Offset is subtracted from the actual "absolute time" value at logging a replication event. That is the event holds logical timestamps in the "relative" format. They are meaningful only in the context of the current binlog. The member is updated (incremented) per binary log rotation. */ int64 offset; ......
state是一个自增的值,offset在每次二进制日志发生rotate时更新,记录发生rotate时的state值。其实state和offset记录的是全局的计数值,而存在二进制日志中的仅是当前文件的相对值。使用LOGICAL_CLOCK的场景以下:
class MYSQL_BIN_LOG: public TC_LOG { ... public: /* Committed transactions timestamp */ Logical_clock max_committed_transaction; /* "Prepared" transactions timestamp */ Logical_clock transaction_counter; ...
能够看到在类MYSQL_BIN_LOG中定义了两个Logical_clock的变量: