Mysql MGR 多主模式下的限制

部署MGR的需求 基础架构


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

 

MGR的一些限制


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中事务的大小

  • 如果可以减少你事务的大小
  • 设定group_replication_transaction_size_limit 来指定组将接受的最大事务大小,默认为05.7中该参数为0,8.0为143M
  • group_replication_compression_threshold 设定消息大小进行压缩的大小,默认为1M

 

DDL和DML的限制举例


多组复制模式故障测试就是将一个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和事务最好在一个节点执行。

 

 

 

你可能感兴趣的:(Mysql)