背景
镇巴ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联公司的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!
有一个业务需要分 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,这些都没有影响。
结果已经说好的只有这一次,那就这样吧,任务成功完成,问题解决失败。
然而,这个问题“才下手头,却上心头”,总有一件事放心不下,约吧。 和开发商量了一下,我们想解决这个问题,知道其所以然,防止在其他业务上出现同样的问题。好吧,再给你们一次机会(来之不易啊)。
那么,再找一个夜深人静的夜晚……这次的月亮好像比上次更圆一些,是好日子的征兆么?
操作之前,还简单规划了一下,下面是当时的一个计划步骤。
^* 黑体的表示已经专门测试过,没有影响
步骤如下。
考虑到先重现问题,首先应该全部使用新配置测试一次,确定问题是否还存在。
因为重点考虑问题是因为 sql_mode 引起的,所以第二次只将这个参数改为老配置,这样就可以测试出其他配置组合时有问题,或者是没有问题,从而得出结论是 sqlmode 的问题。
如果上面还没有找到问题原因,那么就是除了 sql_mode 之外的其他参数组合出了问题(如果没有,则见鬼了)。此时,通过二分法测试,先测试 innodb_flush_log_at_trx_commit、innodb_open_files、sort_buffer_size 三个参数。
如果发现上一步有问题,则再进行二分;如果没有发现问题,则对 sync_binlog、join_buffer_size、tmp_table_size 进行二分。
如果能走到这里,那也是醉了。
再说吧。
按照步骤,一步步地开始做。
首先使用有问题的配置,测试一遍,发现是老样子,还是有问题的(真是幸运,问题还存在)。
把除了 sql_mode 之外的所有参数改成新的,其他都用老配置,测试发现没有问题。
做完了,也是没有问题。
做完了,还是没有问题。
我醉了。
此时当事人已经搞不清楚了,难道是某两个的组合会导致出现这样的问题?如果是这样的话,那情况就太多了,天已经亮了,很累,放弃吧!
就在想放弃的时候,突然有一种新的思路。在有问题的基础上,把所有经过测试没有影响的可以动态修改的参数改成与 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 倍。
总结
这个问题,确实很诡异,万万没有想到是相差那么小的一个变量的问题(以至于一开始就被忽略了)。
这个问题,比较少见,只有表比较多的时候才会比较明显(因为表比较少的时候,算法相对比较稳定)。
这个问题,查明了,其实就是一个算法方面的 BUG。
这个问题,简单的规避方法是单独设置 performance_schema_max_file_instances 值为 0,或者设置 performance_schema_max_file_instances 为一个比较好看的数值,又或者设置 open_files_limit 为 0.65 的整数倍,这样都不会有问题。
这个问题,虽然影响比较小,但我们对问题的探索精神不能没有,要了然于胸。
这个问题,到此为止。
网站标题:大量MySQL表导致服务变慢的问题
当前地址:http://www.shufengxianlan.com/qtweb/news45/523895.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联