【转载】解决mysqld-nt.exe大量占用CPU问题

服务器主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下。此主机有10个左右的 database, 分别给十个网站调用。据朋友测试,导致 mysqld-nt.exe cpu 占用奇高的是网站A,一旦在 IIS 中将此网站停止服务,CPU 占用就降下来了。一启用,则马上上升。 MYSQL CPU 占用 100% 的解决过程

今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000,PageView 为 3万左右。网站A 用的 database 目前有39个表,记录数 60.1万条,占空间 45MB。按这个数据,MySQL 不可能占用这么高的资源。

于是在服务器上运行命令,将 mysql 当前的环境变量输出到文件 output.txt:

d:\web\mysql>mysqld.exe--help>output.txt

发现 tmp_table_size 的值是默认的 32M,于是修改 My.ini, 将 tmp_table_size 赋值到 200M:

d:\web\mysql>notepad c:\windows\my.ini[mysqld]tmp_table_size=200M

然后重启 MySQL 服务。CPU 占用有轻微下降,以前的CPU 占用波形图是 100% 一根直线,现在则在 97%~100%之间起伏。这表明调整 tmp_table_size 参数对 MYSQL 性能提升有改善作用。但问题还没有完全解决。

于是进入 mysql 的 shell 命令行,调用 show processlist, 查看当前 mysql 使用频繁的 sql 语句:

mysql>show processlist;

反复调用此命令(每秒刷两次),发现网站 A 的两个 SQL 语句经常在 process list 中出现,其语法如下:

SELECT t1.pid, t2.userid, t3.count, t1.date FROM _mydata AS t1LEFT JOIN _myuser AS t3 ON t1.userid=t3.useridLEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid ORDER BY t1.pid LIMIT0,15

调用 show columns 检查这三个表的结构 :

mysql>show columns from _myuser;mysql>show columns from _mydata;mysql>show columns from _mydata_body;

终于发现了问题所在:_mydata 表,只根据 pid 建立了一个 primary key,但并没有为 userid 建立索引。而在这个 SQL 语句的第一个 LEFT JOIN ON 子句中:

LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid

_mydata 的 userid 被参与了条件比较运算。于是我为给 _mydata 表根据字段 userid 建立了一个索引:

mysql>ALTER TABLE `_mydata` ADD INDEX ( `userid` )

建立此索引之后,CPU 马上降到了 80% 左右。看到找到了问题所在,于是检查另一个反复出现在 show processlist 中的 sql 语句:

SELECT COUNT(*)FROM _mydata AS t1, _mydata_key AS t2WHERE t1.pid=t2.pid and t2.keywords=
‘孔雀‘

经检查 _mydata_key 表的结构,发现它只为 pid 建了了 primary key, 没有为 keywords 建立 index。_mydata_key 目前有 33 万条记录,在没有索引的情况下对33万条记录进行文本检索匹配,不耗费大量的 cpu 时间才怪。看来就是针对这个表的检索出问题了。于是同样为 _mydata_key 表根据字段 keywords 加上索引:

mysql>ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` )

建立此索引之后,CPU立刻降了下来,在 50%~70%之间震荡。

再次调用 show prosslist,网站A 的sql 调用就很少出现在结果列表中了。但发现此主机运行了几个 Discuz 的论坛程序, Discuz论坛的好几个表也存在着这个问题。于是顺手一并解决,cpu占用再次降下来了。

至此,问题解决。
1. 增加 tmp_table_size 值。mysql 的配置文件中,tmp_table_size 的默认大小是 32M。如果一张临时表超出该大小,MySQL产生一个 The table tbl_name is full 形式的错误,如果你做很多高级 GROUP BY 查询,增加 tmp_table_size 值。 这是 mysql 官方关于此选项的解释:

tmp_table_size
This variable determines the maximum size for a temporary table in memory. If the table becomes too large, a MYISAM table is created on disk. Try to avoid temporary tables by optimizing the queries where possible, but where this is not possible, try to ensure temporary tables are always stored in memory. Watching the processlist for queries with temporary tables that take too long to resolve can give you an early warning that tmp_table_size needs to be upped. Be aware that memory is also allocated per-thread. An example where upping this worked for more was a server where I upped this from 32MB (the default) to 64MB with immediate effect. The quicker resolution of queries resulted in less threads being active at any one time, with all-round benefits for the server, and available memory.

2. 对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX。

索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大,花费时间越多。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要考虑所有数据。如果一个表有1000行,这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。

根据 mysql 的开发文档:

索引 index 用于:

o 快速找出匹配一个WHERE子句的行
o 当执行联结(JOIN)时,从其他表检索行。
o 对特定的索引列找出MAX()或MIN()值
o 如果排序或分组在一个可用键的最左面前缀上进行(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有键值部分跟随DESC,键以倒序被读取。
o 在一些情况中,一个查询能被优化来检索值,不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀,为了更快,值可以从索引树被检索出来。

假定你发出下列SELECT语句:

mysql>SELECT*FROM tbl_name WHERE col1=val1 AND col2=val2;

如果一个多列索引存在于col1和col2上,适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上,优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。

开发人员做 SQL 数据表设计的时候,一定要通盘考虑清楚。

时间: 2024-12-15 01:40:57

【转载】解决mysqld-nt.exe大量占用CPU问题的相关文章

Apache服务器httpd.exe进程占用cpu超过50%的解决方法

httpd.exe进程占用cpu超过50%,关闭掉Apache服务,cpu应用率立刻下降到0.  重新启动Apache又出现占用cpu高的情况.  原因是:httpd.exe和防火墙配置有冲突. 解决方法如下: 1.网上邻居->本地链接->属性->internet协议(TCP/IP)->属性->高级->wins标签->去掉起用LMhosts查询前的勾. 2.控制面版->windows防火墙->高级标签->本地链接设置->服务的标签里勾选安全

System NT Kernel & System占用CPU 12%左右 终极解决方案,原来是更新惹的祸

任务管理器发现 system进程持续占用12%左右的cpu,网上搜索到的很多方法均无效 误打误撞发现了这个方法,亲测可用 卸载系统补丁(KB41000347),提升10%的cpu性能 卸载补丁前:    卸载补丁后:    卸载补丁后cpu性能提升了12%. 卸载方法: 第一种方法:用工具一键卸载 1.退了杀毒软件(360 qq管家) .  2.下载这个(点击下载)工具,鼠标右键工具,用管理员权限打开这个工具即可. 第二种方法:  1. 右键点选电脑-[属性],在弹出视窗选择[控制面板] \ 程

win10 解决 WMI Provider Host 占用CPU过高问题

真心懒得写Blog,但是之前遇到这个问题在网上查了一大圈,几乎一摸一样都是让关防火墙等服务的,然而对于我来说,并没有毛线用. 无奈,直接去微软社区查,还真有一篇问题解决方案.顺手翻译一下放在这里,希望能帮到大家. 参考链接:https://answers.microsoft.com/en-us/windows/forum/windows_10-other_settings/wmi-provider-host-high-cpu-usage-and-laptop/44cb3953-a883-404a

关于csrss.exe和winlogon.exe进程多、占用CPU高的解决办法

原地址 http://blog.sina.com.cn/s/blog_912e77480101nuif.html 最近VPS的CPU一直处在100%左右,后台管理上去经常打不开,后来发现上远程都要好半天才反映过来,看到任务管理器有多个winlogon.exe进程和占用CPU高,百度查了下,说是有人在破解远程,最后按教程修改3389端口和改密码,重启后CPU直接降下来了,winlogon.exe进程也只有一个,一切恢复正常. 我太懒了,之前知道winlogon.exe进程多,但没这几天严重,今天查

php-cgi进程占用cpu资源过大原因分析及解决

一,开启日志记录,为以后排查做准备 1.1 开启php-fpm.conf的错误日志和慢执行日志和常规日志, 采样一个小时,就可以根据这些日志的内容进行分析问题error_log = /tmp/error.log //错误日志access.log = /tmp/access.$pool.log //常规日志,记录每次访问时间,记录不同参数,以防止恶意攻击,后面会详细解析access.format = "%R – %u %t \"%m %r%Q%q\" %s %f %{mili}

tomcat7+java压测过程中占用CPU过高排查故障和解决办法

环架构境: 前端haproxy做为反向代理,后端N+1台tomcat+java服务 出现问题: 环境是新搭建的,本周在做压测刚开始的时候正常,随着量的上涨,导致CPU一直暴涨. 解决办法和思路: 1.)先通过top命令查看占用cpu高的PID # 根据top命令查看发现PID为2195和975的的进程占用CPU高达%200+,明显出现故障 2.)通过top -H -p pid命令查看,发现2275 3302 3375这几个进程占用CPU时间8分钟 3.)把线程pid转换为16进制,例如:上面的p

SQL Server 占用CPU较高的解决方法

触发原因:月底系统结账的时候对ERP的操作较多,有用户反馈系统之间的数据传输很久没有同步.随即到服务器上查看,没有发现有程序导致的问题,看了一下CPU的使用率,发现SQL Server占用率在百分之九十以上. 解决过程:首先Baidu了一下,看了一下可能的原因应该是索引问题.之前有仔细看过SQL Server索引相关的书籍和查找优化索引的方法.所以立即使用SQL Server Profiler开始检测对CPU使用率高的SQL statement. 经过检测发现更新数据传输的语句占用CPU很高(u

exchange2010 sp3 edgetransport.exe 占用CPU 90%以上

随着虚拟化进程加速,公司将所有应用服务器全部迁移到了虚拟化中,自然邮件服务器也要迁移上去,      公司目前由于人数较少,成本有限,故邮件系统采用的是exchange2010 SP3 单台服务器安装了三大角色来满足所有用户使用      安排好迁移时间进行迁移,由于是迁移到ESXI上,故采用的是直接由物理机转换到虚拟机,转换过程很快也很顺利,由于整个数据才50G左右,一个小时完成转换,删除掉一些不用的驱动,拔掉物理机网线,开启虚拟机,一切都很顺利,观察了几分钟后,发现edgetransport

解决挖矿病毒占用cpu以及误删 ld-linux-x86-64.so.2 文件的问题

上次已经被抓去挖矿了当了一次旷工了,本以为解决了,没想到竟然死灰复燃. 这次占用cpu的依然是一个ld-linux的进程,kill掉之后同样就查了关于test用户的进程,果然,test用户的进程有100+个,比不上上次,还是用上次的脚本,将test的进程也kill掉.为防止恶意添加用户,将/etc/passwd 文件里的test用户删除后,给该文件添加了隐藏权限 i ,具体功能不知道的可以查下,此处不多介绍.再把主进程ld-linux干掉之后cpu直接降下来. 这已经是第二次了,为了防止还有第三