MySQL Replication--基于WriteSet的多线程复制
基础知识
基于 COMMIT_ORDER 的并行复制只有在有压力的情况下才可能会形成一组,压力不大的情况下在从库的并行度并不会高。但是基于 WRITESET 的并行复制目标就是在ORDER_COMMIT 的基础上再尽可能的降低 last commit ,这样在从库获得更好的并行度(即便在主库串行执行的事务在从库也能并行应用)。它使用的方式就是通过扫描 Writeset 中的每一个元素(行数据的 hash 值)在一个叫做 Writeset 的历史 MAP(行数据的 hash 值和 seq number 的一个MAP)中进行比对,寻找与当前事务所操作的数据发生"数据冲突"后的最近时间点(Last Committed).
计算PKE方式
在sql\rpl_write_set_handler.cc的add_pke函数中有如下注释:
The next section extracts the primary key equivalent of the rows that are
changing during the current transaction.
1. The primary key field is always stored in the key_part[0] so we can
simply read the value from the table->s->keys.
2. Along with primary key we also need to extract the unique key values to
look for the places where we are breaking the unique key constraints.
These keys (primary/unique) are prefixed with their index names.
In MySQL, the name of a PRIMARY KEY is PRIMARY. For other indexes, if
you do not assign a name, the index is assigned the same name as the
first indexed column, with an optional suffix (_2, _3, ...) to make it
unique.
example :
CREATE TABLE db1.t1 (i INT NOT NULL PRIMARY KEY, j INT UNIQUE KEY, k INT
UNIQUE KEY);
INSERT INTO db1.t1 VALUES(1, 2, 3);
Here the write set string will have three values and the prepared value
before hash function is used will be :
i -> PRIMARYdb13t1211 => PRIMARY is the index name (for primary key)
j -> jdb13t1221 => 'j' is the index name (for first unique key)
k -> kdb13t1231 => 'k' is the index name (for second unique key)
Finally these value are hashed using the murmur hash function to prevent
sending more for certification algorithm.
计算PKE流程
- 如果表中存在索引:
- 将数据库名,表名信息写入临时变量
- 循环扫描表中每个索引:
- 如果不是唯一索引:
- 退出本次循环继续循环。
- 循环两种生成数据的方式(二进制格式和字符串格式):
- 将索引名字写入到pke中。
- 将临时变量信息写入到pke中。
- 循环扫描索引中的每一个字段:
- 将每一个字段的信息写入到pke中。
- 如果字段扫描完成:
- 将pke生成hash值并且写入到写集合中。
- 如果没有找到主键或者唯一键记录一个标记,后面通过这个标记来
- 判定是否使用Writeset的并行复制方式