我们一直在评估我们的MySQL数据库的主动-被动主-主复制设置,运行在版本8.0上。在诊断一些常见的缓慢问题时,我们惊讶地看到这两台服务器上的磁盘IO都很高,从500 on /S到1500 on/S不等。
我发现在这两台服务器上停止从服务器可以将磁盘IO恢复到预期的水平,即15 MB/S- 30 MB/s,而且我担心我们在某个地方出现了错误配置。
这是我查过的:
vmstat显示没有交换。以下是经过编辑的配置:
[mysqld]
...
# General
server_id = <unique_between_servers>
event-scheduler = ON
sync_binlog = 1
log_bin = /var/lib/mysql/mysql-bin
binlog_format = ROW
innodb_file_per_table
innodb_flush_log_at_trx_commit = 1
skip-external-locking
# Replication
relay_log = /var/lib/mysql/mysql-relay-bin
relay_log_recovery = ON
log_slave_updates = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 10000 # 10 seconds
rpl_semi_sync_slave_enabled = 1
# Fine Tuning
key_buffer_size = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
myisam-recover-options = BACKUP
max_connections = 800
max_connect_errors = 1000
innodb_buffer_pool_size = 192G # Server has 256GB RAM
innodb_log_buffer_size = 256M
innodb_log_file_size = 2G
innodb_flush_method = O_DIRECT
innodb_lock_wait_timeout = 60
...我的问题听起来类似于2013年的这个人的死胡同 (你是谁,DenverCoder9 9?你看到什么了?)。
为了解决这个问题,我们简化了测试的设置。我们使用了一个主程序和一个从程序,它们都运行8.0.11,配置与上面相同,并且我们看到了以下根据iostat的写模式(master是蓝色的,从是红色的):

(X轴上的“时间”是当前时间的分钟和秒。)
主服务器上每分钟的1+ GB峰值被跟踪到一个脚本中,该脚本更新两个小表(每个表1000-2000行),磁盘上的大小约为10-15MB。这些表有键,但键不是主键或唯一键。脚本将删除表中的所有行,然后通过每行执行一条INSERT语句重新填充它们,所有语句都在事务中执行。尽管存在明显的问题,但我仍然不明白如何对这么小的表进行操作会导致如此多的磁盘IO。
在没有解决这些问题的情况下,我们返回到主从主从-被动设置,并看到以下内容(主动母版为蓝色,被动母版为红色):

所以我还有几个问题要问。为什么奴隶总是在第一张图中写得比主人多很多?另外,为什么在主-母复制中会出现上面看到的乒乓效应,其中写到主程序会导致从机上产生大量IO,而在主程序上又会产生大量IO?
发布于 2018-06-01 16:44:30
ALTERs被复制了?它们可以是低复制带宽但高I/O。innodb_buffer_pool_size相当大。UNIQUE的索引?变更缓冲区位于buffer_pool中,并异步刷新。请参阅innodb_change_buffer_max_size,但不一定要更改它。TRIGGERs?ROW,一个完整的UPDATE会不会成为STATEMENT呢?SELECTs吗?(打开慢速日志,long_query_time的值很小。)不,我看不出有什么配置变化要做。
一些可能相关的问题(特别是在更新问题之后)
UPDATE,基于行的复制相当冗长。每一行都是复制流中的一个单独的记录,而且它相当大(与更新本身相比)。这些记录将被缓冲并写入主磁盘(binlog)和奴隶的磁盘(中继日志)。我会假设它们是缓冲的,等等,这样的文字量是相同的。但也许我错了。SET autocommit=0;DELETE特定表中的所有1-2K行。如果同时进行基于行的复制,那么就会通过复制流发送大量内容.INSERT一行返回INSERT一行返回COMMIT;,直到这一点,任何东西都会传递给奴隶。我怀疑这是一次编写二进制日志的时候。嗯,我想这仍然没有回答你的问题,但也许它提供了一些更多的洞察力。
这是一种更有效的方法来替换所有的表。它避免了桌子永远无法使用的情况:
CREATE TABLE new LIKE real;
load the new data into the table (LOAD DATA or multi-row INSERT(s) is best)
RENAME TABLE real TO old, new TO real;
DROP TABLE old;发布于 2018-06-08 20:43:40
使用主动-被动主-主安装程序时的复制过程如下(基于使用mysqlbinlog检查二进制和中继日志):
另外,图的底部有一条主要线索:

每当被动主机与磁盘IO挂钩时,主动主程序就会具有零活动,就好像它是阻塞的一样(扰流板:它是)。
这就是我们的结论:
rpl_semi_sync_master_timeout毫秒(默认为10秒)。我们采取了两个步骤来解决这个问题。
首先,我们将rpl_semi_sync_master_timeout缩短为100毫秒。这减少了主动主从在落后时阻塞的时间。我们这样做是为了防止在这种情况再次出现时数据库依赖的应用程序过度挂起。我们愿意承担失去同步的额外风险。
其次,我们重写了导致尖峰的INSERT语句。这些脚本现在使用多行INSERT语句重新填充给定的表,而不是紧循环中的许多单行INSERT语句。
通过这些更改,图现在看起来如下所示。请注意,主动数据库和被动数据库之间的磁盘IO增量要小得多,并且峰值要小得多:

发布于 2018-06-18 18:37:45
建议考虑您的my.cnf-ini 米舍尔德部分
innodb_buffer_pool_instances=8 # from 1 to reduce mutex contention
innodb_lru_scan_depth=100 # from 1024 to conserve CPU cycles every second在每一个情况下。
发布更多要求的信息将为您的安装提供更多性能优化建议。
请查看我的个人资料以获得联系信息。
https://dba.stackexchange.com/questions/207407
复制相似问题