【福利号外】留言送书啦!!本次联合博文视点为广大粉丝提供了送书活动,三位最多点赞的留言粉丝将获得《MySQL运维内参》宝书。 编辑推荐 √ 去哪儿DBA老大 | ACE Director | MySQL用户组主席周彦伟领衔打造 √ 源码专家强势加盟,集三大主流开源项目源码剖析与实战于一书 √ 一呼百应,MySQL官方指定专家特供NoSQL | Replication独家内幕 √ DBA案头必备,覆盖服务器性能 | 集群高可用 | 自动化运维高级话题 有一个业务需要分 1000 个库,每一个库中都有 80 个表,总共就是 80000 * 2 个文件。文件使用率还挺高,大概是 60000 * 2。 这个业务采用的高可用架构是 MMM,由于集群机器在硬件检查时发现有问题,必须要换掉。于是想了一个比较简单、影响面较小的方法去解决,就是找了另外两台机器迁移过去。同时,要求这四台机器属于同一个网段,VIP(虚拟 IP 地址)在机器之间可以漂移,这样业务就不需要修改 IP 地址即可迁移,相当于两次主从切换过程。 切换方案如图 16.1 所示。 从图 16.1 中可以看到,切换过程很简单,如下三步。
以上是背景。
其他方面,环境完全相同,业务方面没有任何更改,重现慢的现象,只是需要切换而已。 图 16.3 是切换过程中的监控图,高起来的就是把流量切换到 db3 的情况,处于低谷的就是切换到 db1 的情况,效果非常明显,慢得立竿见影,好神奇!
但上面这些都只是分析,硬件测试之后,没有发现问题(也不能说就不是硬件的问题,一直吊在那里)。那只剩下配置了,所以接下来从这里入手吧,希望能成功!
首先要做的事情是,把 db3 的读流量切换到 db1,然后把配置完全换成 db1 的配置,将数据库重启,然后上线。此时,db1 是写节点,db3 是读节点,最神奇的时刻即将到来。 切换之后,经过观察,竟然没有问题了。问题已经解决,那么说明还是上面列出来的配置差别引起的问题。 那么解决之后,下面的工作就是重复一开始的工作,把 db1 下线,让 db4 上线。此刻,之前的迁移工作已经完成,线上服务没有问题。 但……开发同学,能给我半个小时,让我看看是哪个参数引起的么? 得到的回答是:“迅速点,就这一次,给你 20 分钟。” 把最有可能的参数找出来,比如字符集(实际上,上面列出的每一个,我们认为都不会有多大影响),考虑到字符集是不可动态修改的参数,所以先把这个改了。重启,然后一个一个地动态修改、业务重启重连等,都没有发现。修改的这些参数包括:sql_mode、join_buffer_size、max_heap_size、sort_buffer_size,这些都没有影响。 结果已经说好的只有这一次,那就这样吧,任务成功完成,问题解决失败。 然而,这个问题“才下手头,却上心头”,总有一件事放心不下,约吧。 和开发商量了一下,我们想解决这个问题,知道其所以然,防止在其他业务上出现同样的问题。好吧,再给你们一次机会(来之不易啊)。
操作之前,还简单规划了一下,下面是当时的一个计划步骤。 ^* 黑体的表示已经专门测试过,没有影响 步骤如下。
按照步骤,一步步地开始做。
此时当事人已经搞不清楚了,难道是某两个的组合会导致出现这样的问题?如果是这样的话,那情况就太多了,天已经亮了,很累,放弃吧! 就在想放弃的时候,突然有一种新的思路。在有问题的基础上,把所有经过测试没有影响的可以动态修改的参数改成与 db1 相同的参数,这样应该是最少量的可以影响到性能的参数组合了。此时,在 db1 与 db3 实例上分别执行 show variables,全量导出变量,进行对比,发现有几个参数的区别(左边是老的 db1,右边是新的 db3),如图 16.4 所示。 此时,我们做了最后的挣扎,已经只剩下这 6 个了,看上去还是不会有什么影响,有些已经试过了,再随便试一次吧。二分查找,从下面开始找了三个参数,下线、重启、上线……发现问题竟然奇迹般地存在。而此时只剩下了三个参数,其中一个参数是 sync_binlog,有问题的是 0,肯定不会影响啊。只能定位到剩下的两个了,可以看到倒数第二个是一个 performance_schema 的参数,配置文件中没有设置,是默认的,可以忽略。于是,把问题定位到 open_files_limit 了。 此时,再做最后一次,只剩下 open_files_limit 的区别了。结果还是有问题,说明就是这个参数了。 回过头来想了一下,其实当初看区别的时候,这两个参数就在配置文件中,只是看着 13 万和 15 万相差不大,就忽略了。好吧,问题已经解决,找到了原因,天亮了,回家吧。 已经查到了是 open_files_limit 的原因。那么,究竟为什么在一个参数相差这么小的情况下会影响 10 倍的性能呢?查查源码! 通过 sysbench,创建 60000 个表,每个表 10000 行,在只读模式下,发现设置为 130000 时,QPS 可以达到 20000,而设置为 150000 的时候,QPS 只有 4000 左右。问题重现了,就简单多了。 此外,还有一个额外的发现。如果设置为 150000 之后,重启数据库,非常慢,大概需要 1 分钟,而设置为 130000 之后,只需要 10 秒左右。查看了一下在很慢的过程中 mysqld 的线程情况。其中,在启动的过程中,有一个线程长时间都基本处于同一个堆栈,使用 pstack mysqldpid 查看,如图 16.5 所示。 还有一个发现就是,当设置 open_files_limit 为相同的时候,performance_schema_max_file_instances 参数也相同了,并且这个参数没有设置过。那么,通过源码发现,这个参数竟然是通过 open_files_limit 值来设置的。如果 open_files_limit 值设置得比较大(这样就可以忽略掉其他影响条件,比如 max_connection 等),performance_schema_max_file_instances 的值直接就是从 open_files_limit/0.65 得来的(源码对应函数 apply_load_factor)。这样就知道了,130000/0.65 正好是 200000,150000/0.65 正好是 230770,与图 16.4 所示相符合。 另外,通过测试发现,如果单独设置 performance_schema_max_file_instances 为不相同的值,而将 open_files_limit 设置为相同,性能还是不一样。从而可以确定与 open_files_limit 参数实际上没有什么关系,只是 performance_schema_max_file_instances 使用了默认值,它的值就来源于 open_files_limit/0.65 了,这样间接影响了 performance_schema_max_file_instances 值,突然有种“隔山打牛”的感觉。 还有一个发现,如果将 performance_schema_max_file_instances 设置为 200000、210000、220000、230000、240000、300000 等,性能都是差不多的,唯独设置为 230770 是有问题的。仔细研究之后发现,performance_schema_max_file_instances 最终影响的是 performance_schema 数据库中的 file_instances 表,这个表中的数据是通过一个 HASH 表来缓存的,而这个参数决定的是该 HASH 表的大小。 后面又做了一个非常无聊的测试,是 performance_schema_max_file_instances 值与 QPS 的对比,如图 16.6 所示。 至此,一切都豁然开朗了。结合上面非常慢的堆栈,以及将 performance_schema_max_file_instances 设置为不同值的现象,可以确定,这个问题最终是 HASH 算法的问题。当 HASH 桶大小为一个比较好看的数值时,这个算法就非常快,而如果是一个比较零碎的值时,算法就非常慢了,会导致响应时间是原来的 10 倍。
2017 年,有哪些值得关注的运维技术热点?智能化运维、Serverless、DevOps ......CNUTCon 全球运维技术大会将于 9 月上海举办,12 位大牛联合出品,揭秘最前沿运维技术,推荐学习! |
|