mssql数据库占用CPU过高?

mssql数据库占用CPU过高?,第1张

CPU占用过高诊断思路

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使用率对比

杀掉lock进程最快的方法是重启mysql,像你这种情况,1000多sql锁住了,最好是重启

如果不允许重启,我提供一个shell脚本,生成 kill id命令杀掉lock线程,如下:

------------------------------------

#!/bin/bash

mysql -u root -e "show processlist"|grep -i "Locked" >>locked.txt

for line in awk '{print $1}' locked.txt

do

echo "kill $line">>kill_lock.sql

done

----------------------------------

执行完脚本后,会生成kill_lock.sql文件,内容类似如下:

kill 1

kill 2

kill 3

-------------------这些对应的都是lock的sessionid,直接复制文件里的内容,然后在mysql里执行就ok 了

至于排查哪条sql引起的,这个有点难了,不过你可以尝试开启慢查日志和无索引日志来确认比较耗时的查询,避免再次出现堵塞

redis只是一个缓存,一般存在内存里。

而mysql大部分时间会在磁盘IO,也就是性能瓶颈多半在磁盘。而且由于写的 *** 作,一般都在mysql上面,也就是CPU一直会等待mysql写入的 *** 作,毕竟读内存速度基本是磁盘的几百倍,甚至上万倍。

另外一方面,redis比较简单,数据结构比较清晰,而mysql作为一个关系型数据库,可能涉及到很多复杂的数据结构,比如事务和锁之类的 *** 作,非常占用CPU性能。

所以肯定是mysql占用的CPU和时间大大超过redis。这建立在读写量差不多的情况下。如果你主要用redis读数据,mysql只是辅助,那么mysql也占用不了多少性能。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/8504788.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-17
下一篇 2023-04-17

发表评论

登录后才能评论

评论列表(0条)

保存