诊断思路
mpstat -P ALL 1,查看cpu使用情况,主要消耗在sys即os系统调用上
perf top,cpu主要消耗在_spin_lock
生成perf report查看详细情况
CPU主要消耗在mutex争用上,说明有锁热点。
采用pt-pmp跟踪mysqld执行情况,热点主要集中在mem_heap_alloc和mem_heap_free上。
Pstack提供更详细的API调用栈
Innodb在读取数据记录时的API路径为
row_search_for_mysql --》row_vers_build_for_consistent_read --》mem_heap_create_block_func --》mem_area_alloc --》malloc --》 _L_unlock_10151 --》__lll_unlock_wait_private
row_vers_build_for_consistent_read会陷入一个死循环,跳出条件是该条记录不需要快照读或者已经从undo中找出对应的快照版本,每次循环都会调用mem_heap_alloc/free。
而该表的记录更改很频繁,导致其undo history list比较长,搜索快照版本的代价更大,就会频繁的申请和释放堆内存。
Linux原生的内存库函数为ptmalloc,malloc/free调用过多时很容易产生锁热点。
当多条 SQL 并发执行时,会最终触发os层面的spinlock,导致上述情形。
解决方案
将mysqld的内存库函数替换成tcmalloc,相比ptmalloc,tcmalloc可以更好的支持高并发调用。
修改my.cnf,添加如下参数并重启
[mysqld_safe]malloc-lib=tcmalloc
上周五早上7点执行的 *** 作,到现在超过72小时,期间该实例没有再出现cpu长期飙高的情形。
以下是修改前后cpu使用率对比
有很多种方法可以优化:数据库设置主从,进行读写分离;
数据分表,如按月份分表,需要统计数据就查总表;
优化查询语句,适当增加索引;
字段优化,对不常用或者没有必要的字段可以考虑放在另外一张表里,避免单表数据过大,字段过多。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)