my31_MGR单写模式压测以及对比普通从库记录
场景
MGR单写模式三节点,db46写节点,db47/db48为读节点
工具sysbencn、压测15个小时,db46上18线程纯写,12线程oltp混合测试,db48上12线程select
在压测2个小时后,两个从库就卡住不再写,前一天晚上起的脚本,第二天来发现的这个问题,然后开始尝试解决
日志信息
2019-03-01T12:35:23.921815+08:00 2763 [Note] Multi-threaded slave statistics for channel 'group_replication_applier': seconds elapsed = 568; events assigned = 185124865; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 2030997800 waited (count) when Workers occupied = 75103 waited when Workers occupied = 22073734900
2019-03-01T12:37:29.742741+08:00 2763 [Note] Multi-threaded slave statistics for channel
'group_replication_applier': seconds elapsed = 126;
events assigned = 185125889;
worker queues filled over overrun level = 0;
waited due a Worker queue full = 0;
waited due the total size = 0;
waited at clock conflicts = 2032822300 waited (count) when Workers occupied = 75114
waited when Workers occupied = 22075589000
读节点无法关闭集群,一直卡
mysql> stop group_replication;
卡的过程中报相关日志
2019-03-01T12:54:22.192891+08:00 16 [ERROR] Plugin group_replication reported: 'Timeout on wait for view after joining group'
2019-03-01T12:54:22.192959+08:00 16 [Note] Plugin group_replication reported: 'Requesting to leave the group despite of not being a member'
2019-03-01T12:54:22.193012+08:00 16 [ERROR] Plugin group_replication reported: '[GCS] The member is leaving a group without being on one.'
2019-03-01T12:54:22.193109+08:00 0 [Warning] Plugin group_replication reported: 'read failed'
2019-03-01T12:54:22.193211+08:00 0 [Warning] Plugin group_replication reported: '[GCS] The member has left the group but the new view will not be installed, probably because it has not been delivered yet.'
2019-03-01T12:54:27.193393+08:00 16 [Note] Plugin group_replication reported: 'auto_increment_increment is reset to 1'
2019-03-01T12:54:27.193414+08:00 16 [Note] Plugin group_replication reported: 'auto_increment_offset is reset to 1'
2019-03-01T12:54:27.193598+08:00 164 [Note] Error reading relay log event for channel 'group_replication_applier': slave SQL thread was killed
2019-03-01T12:54:27.194129+08:00 164 [Note] Slave SQL thread for channel 'group_replication_applier' exiting, replication stopped in log 'FIRST' at position 374
2019-03-01T12:54:27.194564+08:00 161 [Note] Plugin group_replication reported: 'The group replication applier thread was killed'
强制kill了读节点db48 mysql进程后,无法再次加入集群
mysql> start group_replication;
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> start group_replication;
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.
在现写节点db46上执行stop group_replication;依然是卡住, 过一段时间之后,写节点切换到另外一个节点db47上了,
此时db48正常关闭实例,再次启动后,尝试start group_replication;加入了集群,查看写节点为db47
原来的写节点db46已经不在集群中了
mysql> SELECT MEMBER_ID,MEMBER_HOST,MEMBER_PORT,MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+------------+-------------+--------------+
| MEMBER_ID | MEMBER_HOST| MEMBER_PORT | MEMBER_STATE |
+--------------------------------------+------------+-------------+--------------+
| 3b6d8d58-3b31-11e9-b581-6c92bfb23298 | db47 | 3301 | ONLINE |
| d29a16c7-3b2f-11e9-8c10-6c92bfb234c0 | db48 | 3301 | RECOVERING |
+--------------------------------------+------------+-------------+--------------+
重点是,写入db46的数据,由于复制进程卡住,还会同步到db47上吗,毕竟从状态上看db46已经不在集群中了
查看db47的数据文件,发现文件大小不变且小于db46上的文件,即没有再从db46上同步数据,
但db48是从db47上同步数据的,db47/db48都落后于db46,但db48落后的更多,所以db47成为写节点后,db48开始从db47追数据
数据丢失是业务不能接受的,宁可全部舍弃db47与db48,也不会舍弃db46,因为db46数据是全的;
至此,已经可以得到两个观点
1. 追加从库要直接加在写节点的下面,不要加在读或从节点的下面;因为读节点要挂了,之后的节点数据皆不全
2. MGR正常的切换是在保证节点数据一致或节点间复制、通信正常为前提的;如果正常命令无法执行,
比如无法stop group_replication,就代表着此时集群有问题,
在关闭之前,应该先记录一下出问题的位置,查看一下日志报错等
不要上来就强制关闭实例,更不要重置节点,做这些之前要先想好恢复的方案
下面优先恢复写节点,在原写节点db46上执行
set global group_replication_bootstrap_group=on;
start group_replication;
set global group_replication_bootstrap_group=off;
重置节点db47,这是原来的操作步骤,没有记录执行的位置就重置了,是错误的操作,
由于实际操作时是这么做的,就记录一下,后面对此做法的数据恢复也做了分析
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000047
Position: 270
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 3b6d8d58-3b31-11e9-b581-6c92bfb23298:1-583,
aaaaaaaa-bbba-ccca-ddda-aaaaaaaaa104:1-52150701,
c7a444f8-3b30-11e9-8336-6c92bfb2329c:1-49
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> reset master;
Query OK, 0 rows affected (5.23 sec)
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 150
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> start group_replication;
Query OK, 0 rows affected (7.58 sec)
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 1946
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: aaaaaaaa-bbba-ccca-ddda-aaaaaaaaa104:1-4,
c7a444f8-3b30-11e9-8336-6c92bfb2329c:1-2
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> SELECT MEMBER_ID,MEMBER_HOST,MEMBER_PORT,MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+------------+-------------+--------------+
| MEMBER_ID | MEMBER_HOST| MEMBER_PORT | MEMBER_STATE |
+--------------------------------------+------------+-------------+--------------+
| 3b6d8d58-3b31-11e9-b581-6c92bfb23298 | db47 | | RECOVERING |
| c7a444f8-3b30-11e9--6c92bfb2329c | db46 | | ONLINE |
+--------------------------------------+------------+-------------+--------------+
不指定恢复的起点时,MGR默认是从头开始恢复的,可以看到日志中MGR在尝试启动,但启动不起来,最后就放弃从开始的位置开始同步数据了
2019-03-01T14:14:10.430561+08:00 928 [Note] 'CHANGE MASTER TO FOR CHANNEL 'group_replication_recovery' executed'. Previous state master_host='db46', master_port= 3301, master_log_file='', master_log_pos= 4, master_bind=''. New state master_host='<NULL>', master_port= 0, master_log_file='', master_log_pos= 4, master_bind=''.
2019-03-01T14:14:10.432469+08:00 928 [Note] Plugin group_replication reported: 'Retrying group recovery connection with another donor. Attempt 2/10'
使用db48以指定的执行位置开始恢复
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000045
Position: 59480248
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: aaaaaaaa-bbba-ccca-ddda-aaaaaaaaa104:1-49285172,
c7a444f8-3b30-11e9-8336-6c92bfb2329c:1-49
1 row in set (0.00 sec)
reset master;
SET @@GLOBAL.GTID_PURGED='aaaaaaaa-bbba-ccca-ddda-aaaaaaaaa104:1-49285172,c7a444f8-3b30-11e9-8336-6c92bfb2329c:1-49';
start group_replication;
对于db47,先执行了reset master,之前的日志清空,位置重新开始;之前db48是落后于db47的,
如果让db47从db48的位置开始同步,那么必定存在大量的重复数据,分以下情况讨论
1. insert,由于是日志方式的同步,insert同样的数据时,会提示主键同步,报1062错误;可在配置文件中跳过1062错误即可
2. update,相同的数据会再次update一遍,比如set a=1,a字段本来就是1,再执行一次set a = 1,a字段的值还是1,数据正确性没有被破坏
3. delete,删除一条数据,由于是重复执行,此时会报1032错误-删除的数据不存在,跳过后不影响数据的正确性
测试期间并未做DDL操作,预期db47 online恢复后,数据应该与db46一致,等待恢复结束后再验证
同步完成之后,写库db46测试表| 61272706 行记录,db47也是| 61272706 |条记录,行数与预期的一致
但行数一致并不真正代表每一行的数据是一致的,此时时间有限,不细验证这个了,
简单地认为追加了13个小时延迟数据,有insert也有delete,数据量在6千万的情况下还能保持行数一致,数据就是一致的
至此,这套库数据恢复;再提一下最开始日志的信息中有写
waited when Workers occupied = 22075589000
Workers被占用而导致的等待,解决方法为调大slave_pending_jobs_size_max参数
mysql> show variables like 'slave_pending_jobs_size_max';
+-----------------------------+----------+
| Variable_name | Value |
+-----------------------------+----------+
| slave_pending_jobs_size_max | |
+-----------------------------+----------+
row in set (0.00 sec)
服务器配置比较高,所以我设置了一个比较大的值
set global slave_pending_jobs_size_max=64424509440;
这是修改运行状态中的参数设置,重启实例就失效了,在配置文件中添加
slave_pending_jobs_size_max=64424509440
下面进行另外一个测试,把db48 从MGR集群中去掉,变成普通的从库挂载到db46进行压测
对比普通从库与MGR读节点的性能差异
MGR读节点db48转普通主从
stop group_replication;
CHANGE MASTER TO MASTER_HOST='db46',MASTER_PORT=3301,MASTER_USER='rpl_user',MASTER_PASSWORD='11111111',MASTER_AUTO_POSITION=1;
start slave;
show slave status\G;
结论:
现象1:MGR在压力大的情况下,两个读节点全挂了,写节点正常
结论1:MGR读节点不如写节点能抗压力,MGR集群在压力大的情况下读节点挂掉的概率高于写节点
现象2:同样的硬件环境下,MGR一写一读、一从,读的性能不如从高
结论2:MGR在高压力环境读节点比普通从库性能有损耗,损耗多少可能与硬件配置、压力的大小有关,要具体测试验证
措施:
1. MGR集群下再挂一些普通从库,作为线上运行数据库的灾备库使用;
2. MGR读节点的硬件配置、性能需求可以比写读高一些
3. 在业务允许延迟的系统中,MGR一写一读+两从库,两从对外提供服务,MGR的读不对外使用,作为灾备库,故障时自动切换; 不差机器可以采用 3(MGR)+2(从)的方式。
4. 侧重于高可用,可以采用3(mgr)+ 1(从),从作为灾备使用,三个MGR节点负责高可用
my31_MGR单写模式压测以及对比普通从库记录的更多相关文章
- Jmeter(一)非GUI模式压测(NON-GUI模式)结果解析TPS
非GUI模式压测(NON-GUI模式)结果解析TPS 准备工作 从脚本已录制成功之后开始进行压测 安装Jmeter拓展插件 查看 Transactions per Second https://jme ...
- SwingBench 字符模式压测最佳实践
之前写过<使用SwingBench 对Oracle RAC DB性能 压力测试>,使用的是最基础直观的图形模式,已经可以满足大多数需求. 但是在有些场景下,图形模式可能本身消耗资源过大,尤 ...
- Jmeter之http性能测试实战 非GUI模式压测 NON-GUI模式 结果解析TPS——干货(十一)
性能测试计划 性能测试用例 录制脚本 性能测试结果 性能测试报告 性能测试监控报告 准备工作 从脚本已录制成功之后开始进行压测 安装Jmeter拓展插件 查看 Transactions per Sec ...
- 手把手用Monkey写一个压测脚本
版权声明: 本账号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影所有. 允许有条件转载,转载请附带底部二维码. 一.为什么需要一个测试脚本? 昨天讲解了Android Monkey命 ...
- 系统压测结果对比:tomcat/thinkphp/swoole/php-fpm/apache
[测试所用服务器8核,16G内存]压测接口:很简单,从一张表里根据主键随机查询出一条数据[数据库服务器和WEB服务器分开的].表数据量大概:910000+条. 这个测试结果很有趣:tp5.0和3.2性 ...
- JMeter-命令行模式压测
前言 使用非GUI模式,即命令行模式运行jmeter测试脚本能够大大缩减系统资源,今天跟小伙伴们讲一下JMeter如何在命令行模式进行压测吧! 一:配置好JDK和JMeter的环境变量(过程略) 二: ...
- MGR架构~单写模式架构的搭建
一 简介 :MGR一直没有时间测试,今天咱们来初步了解搭建一下呗 二 环境: mysql5.7.20 单台机器 启动三实例 三 mysql 搭建: 1 建立相关目录+ mkdir -p /data ...
- Apache自带 ab压测工具 Windows配置使用说明 - 随笔记录
我们先来了解一下ab工具的概念,摘自网络: ab是apache自带的压力测试工具.ab非常实用,它不仅可以对apache服务器进行网站访问压力测试,也可以对或其它类型的服务器进行压力测试.比如ngin ...
- 并发模式与 RPS 模式之争,性能压测领域的星球大战
本文是<如何做好性能压测>系列专题分享的第四期,该专题将从性能压测的设计.实现.执行.监控.问题定位和分析.应用场景等多个纬度对性能压测的全过程进行拆解,以帮助大家构建完整的性能压测的理论 ...
随机推荐
- [转]xe6 android 使用距离传感器(Proximiry)
The first step it's a run sample from RAD Studio that named SensorInfo on your device. On the tab Bi ...
- Sql Server 日期格式化函數 Convert
Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2015 10:57AM Select CONVERT(varchar(100), GETDATE( ...
- TSQL--SET ANSI_NULLS OFF
当ANSI_NULLS 为ON时,遵循SQL92的标准,只能使用IS NULL 来判断值是否为NULL, 而不能使用=或<>来与NULL做比较,任何值包括NULL值与NULL值做=或< ...
- Ubuntu下vi编辑器不听话
编辑文件/etc/vim/vimrc.tiny,将“compatible”改成“nocompatible”非兼容模式: 并添加一句:set backspace=2
- C#生成静态文件
一般生成文件都是通过读取模板文件,然后替换标签. 这些古老的方法使用起来不但麻烦而且效率还不怎么样. 这里给添加介绍一个方法. 如果你用过asp.net.mvc (Razor),你就应该明白 chtm ...
- 温故而知新:什么是wcf
1.什么是WCF.WCF是Windows Communication Fundation的缩写,是微软在.net 3.0 的时候引进的,用于开发可交互的分布式应用程序,是由微软发展的一组数据通信的应用 ...
- 搭建linux虚拟机
一.VMware 9 安装CentOS 7 -> 创建新虚拟机, 选择稍后安装操作系统 -> 选择Linux系统Centos 64位 -> 填写虚拟机名称, 选择虚拟机安 ...
- jstack应用-查找CPU飚高的原因
场景 在系统上线后,经常会遇到运维的同学跑过来说:“这次发版后,cpu线程使用率到一场,到100%了”.这时候不要慌,可以使用堆转储来分析到底是哪个线程引起的. 查找元凶 发现pid=17850的进程 ...
- linux联网配置(更新)
重启网络配置:service network restart: 常见问题: linux 虚拟机ifconfig 显示eth1 文件ifcfg-eth0中device为eth0的问题 为什么eth0 ...
- JSON Assertion(JSON断言)
JSON断言允许你完成对JSON文档的校验,首先,如果如果数据不是JSON,则会解析失败:其次,JMeter会用指定语法寻找指定的path,如果没有找到,则会失败:第三,如果验证期望值为null,JM ...