innodb存储引擎
数据必须存储在innodb存储引擎内
我们通过设置如下参数来禁用其他存储引擎
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
主键
每张表都必须定义一个主键或者等价的非空的唯一键
IPv4网络
服务器必须支持IPv4网络
网络性能
MGR组中的各个服务器必须相互联通且网络性能要求较高
binlog日志
必须开启二进制日志文件功能
--log-bin[=log_file_name]
Slave Updates Logged
组内中的服务器必须可以记录所有事务的日志
--log-slave-updates
二进制日志格式
必须设定二进制日志格式为row
--binlog-format=row.
Binary Log Checksums Off
设定 --binlog-checksum=NONE.
开启GTID
必须开启GTID功能,用来检测MGR中事务的执行情况
Replication Information Repositories
必须设定如下参数记录主从库的元数据信息
--master-info-repository=TABLE
--relay-log-info-repository=TABLE
Transaction Write Set Extraction
设置如下参数使在记录日志的时候同时记录写集,用来检测冲突
--transaction-write-set-extraction=XXHASH64
Lower Case Table Names
设置--lower-case-table-names 参数为同一个值
innodb中设置为1 注意不同平台的该值可能不一致
Multithreaded Appliers
我们可以设定一些参数使同步进程并行起来
--slave-parallel-workers=N
--slave-preserve-commit-order=1
--slave-parallel-type=LOGICAL_CLOCK
Gap Locks
MGR推荐使用 READ COMMITTED 隔离级别来避免使用Gap Locks
Table Locks and Named Locks
MGR的验证过程不考虑table locks 和named locks Replication Event Checksums
MGR无法使用复制事件检测
SERIALIZABLE隔离级别
MGR不支持串行化隔离级别
DDL和DML
多主模式下,MGR不支持同时不同服务器上的同一个对象的的DDL和DML
级联约束的外键索引
多主模式下,MGR不支持级联约束的外键索引
MySQL Enterprise Audit and MySQL Enterprise Firewall
MySQL 5.7.21以前,MySQL Enterprise Audit and MySQL Enterprise Firewall使用的是MyISAM表,所以不支持
多主模式下死锁
多主模式下,SELECT .. FOR UPDATE语句会引发死锁
Replication Filters
MGR不支持复制过滤
组大小
MGR最多可以有9个成员
事务大小的限制
一个成员的独立事务如果过大可能会导致无法在5s内传输到各个节点,这时可能会踢出该成员如果我们不设置单独参数限定大小的话,默认为slave_max_allowed_packet参数的大小,默认是1G
如果单个事务导致消息内容足够大,以致于无法在5秒的时间内通过网络在组成员之间复制消息,则可能会怀疑成员失败了,然后将其驱逐出局。
我们可以使用如下方法限定MGR中事务的大小
多组复制模式故障测试就是将一个kill掉,然后两个还是online的,因为都是主,可读可写,所以不会发生故障切换,可以看到都是主,所以该值为空,如果是单主模式这里会有一个值,指定那个机器为主
mysql> show global status like '%primary_member%';
+----------------------------------+-------+
| Variable_name | Value |
+----------------------------------+-------+
| group_replication_primary_member | |
+----------------------------------+-------+
在多主模式下面做DML操作会做一个冲突监测,如delete insert update DDL比较特殊,如修改表结构
DDL语句并发执行的问题:
多主复制时,通过冲突检测来辨别有冲突的事物,有冲突的事务进行回滚。MySQL DDL无法回滚,group replication没有对DDL做冲突检测。在同一库DDL会被阻塞。修改隔离级别为READ-COMMITTED
Db01
update t set c1=’aaa’;
还没提交,在另外一个会话做一个操作
Alter table t add c2 此时此刻该语句会阻塞
在同一个库会被阻塞,在不同库不做冲突监测,会出现一些问题
默认级别可重复读
mysql> show variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
开发模式使用读以提交 db01 db02 db03配置
transaction_isolation= READ-COMMITTED
group_replication_single_primary_mode=off
group_replication_enforce_update_everywhere_checks=ON
[root@db01 ~]# systemctl start mysqld
mysql> show variables like '%isolation%';
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
Db01 先引导
mysql> stop group_replication;
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Db02
mysql> stop group_replication;
mysql> start group_replication;
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 18f5da07-a096-11ea-8c70-000c290e1abf | db01 | 3306 | ONLINE |
| group_replication_applier | 7d3e894a-a0a9-11ea-82f8-000c29a7fff7 | db03 | 3306 | ONLINE |
| group_replication_applier | dfe895a8-a0df-11ea-bb7d-000c296190c1 | db02 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
Db03依次类推
修改隔离级别为READ-COMMITTED,transaction_isolation= READ-COMMITTED
db01 |
db02 |
begin; insert into v1 values(1); |
|
|
truncate t1; |
commit; |
|
db01
mysql> create table v1(id int primary key);
mysql> begin;
mysql> insert into v1 values(1);
还没提交
这个时候db02
mysql> select * from v1; 因为是读以提交,db01没有提交,所以看不到数据
Empty set (0.00 sec)
mysql> truncate v1;
神奇的事情发生了
Db01查看数据
mysql> commit;
mysql> select * from v1;
Empty set (0.00 sec)
Db02
mysql> select * from v1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
Db03
mysql> select * from v1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
可以看到数据一致性不一样了
db01上两个事物的执行顺序:
insert into v1 values(1);
truncate t1; 在insert执行还没提交在db02上truncate的操作同步过来了,即在commit之前就是上面两个事务
如果truncate执行是在db01上执行的那么会发生阻塞,等insert commit之后才truncate
db02上两个事物的执行顺序:
truncate t1;
insert into v1 values(1);
可以看到DDL语句并发是有问题的,生产环境使用了多主模式一定要注意,ddl和事务最好在一个节点执行。