使用ci 发现mysql sleep进程过多

本文探讨了MySQL中sleep连接过多的问题及影响,分析了其产生的原因,并提供了调整wait_timeout参数的具体步骤,以改善系统性能。

用ci开发了一个网站,发现mysql经常提示连接数过多,登陆mysql,用show processlist发现很多sleep的进程,原理是在application/config/database.php中设置了$db['default']['pconnect'] = TRUE;在mysql中用show global variables like 'wait_timeout';显示wait_timeout=28800。原来是在ci中开了pconnect,且在mysql中wait_timeout为默认值28800,导致MySQL里大量的SLEEP进程无法及时释放,拖累系统性能。


关于sleep进程过多的文章。http://blog.163.com/sujoe_2006/blog/static/33531512011521113038227/

如果你没有修改过MySQL的配置,缺省情况下,wait_timeout的初始值是28800。

wait_timeout过大有弊端,其体现就是MySQL里大量的SLEEP进程无法及时释放,拖累系统性能,不过也不能把这个指设置的过小,否则你可能会遭遇到“MySQL has gone away”之类的问题,通常来说,我觉得把wait_timeout设置为10是个不错的选择,但某些情况下可能也会出问题,比如说有一个CRON脚本,其中两次SQL查询的间隔时间大于10秒的话,那么这个设置就有问题了(当然,这也不是不能解决的问题,你可以在程序里时不时mysql_ping一下,以便服务器知道你还活着,重新计算wait_timeout时间):

# vi /etc/my.cnf

[mysqld]
wait_timeout=10

# /etc/init.d/mysql restart

不过这个方法太生硬了,线上服务重启无论如何都应该尽可能避免,看看如何在MySQL命令行里通过SET来设置:

mysql> set global wait_timeout=10;

mysql> show global variables like 'wait_timeout';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| wait_timeout               | 10    |
+----------------------------+-------+

这里一个容易把人搞蒙的地方是如果查询时使用的是show variables的话,会发现设置好像并没有生效,这是因为单纯使用show variables的话就等同于使用的是show session variables,查询的是会话变量,只有使用show global variables,查询的才是全局变量。

网络上很多人都抱怨说他们set global之后使用show variables查询没有发现改变,原因就在于混淆了会话变量和全局变量,如果仅仅想修改会话变量的话,可以使用类似set wait_timeout=10;或者set session wait_timeout=10;这样的语法。

另一个值得注意的是会话变量wait_timeout初始化的问题,这一点在手册里已经明确指出了,我就直接拷贝了:

On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client (as defined by the CLIENT_INTERACTIVE connect option to mysql_real_connect()).

MySQL大拿Jeremy Zawodny曾在他的文章Fixing Poor MySQL Default Configuration Values里面列出了几个很恶心的MySQL缺省设置,不过没包含wait_timeout,但我觉得它也应该算一个,每次新装MySQL后最好都记得修改它。


参考文章2
睡眠连接过多,会对mysql服务器造成什么影响?

严重消耗mysql服务器资源(主要是cpu, 内存),并可能导致mysql崩溃。

造成睡眠连接过多的原因?

1. 使用了太多持久连接(个人觉得,在高并发系统中,不适合使用持久连接)

2. 程序中,没有及时关闭mysql连接

3. 数据库查询不够优化,过度耗时。

那么,如果要从根本上解决sleep连接过多,就得从以上三点反复检查,但是见效并不快。

网上有人分享,使用shell脚本配合cron,定期杀死睡眠时间太久的连接,但是这种方法非常不可取,典型的以暴制暴,很可能导致数据崩溃,而且,还需要编写相应shell, 设置cron, 实施成本较繁琐,不推荐使用。

那么更好的办法应该是让mysql自己决定这些睡眠连接的命运,实施会更简单,有效。

mysql的配置文件中,有一项:

wait_timeout, 即可设置睡眠连接超时秒数,如果某个连接超时,会被mysql自然终止,多好的办法!

如设置: 

wait_timeout=100 #即设置mysql连接睡眠时间为100秒,任何sleep连接睡眠时间若超过100秒,将会被mysql服务自然终止,要比编写shell脚本更简单。

那么,对于正在运行中的生产服务器,在不能停止服务情况下,修改此项怎么办?很简单,以root用户登录到mysql,执行:

set global wait_timeout=100

即可。

在我的生产环境中,使用这个办法,取得了相当好的效果。

当然,更根本的方法,还是从以上三点排查之:

1. 程序中,不使用持久链接,即使用mysql_connect而不是pconnect。

2.   程序执行完毕,应该显式调用mysql_close

3. 只能逐步分析系统的SQL查询,找到查询过慢的SQL,优化之

<think>嗯,用户现在问的是MySQL数据库CPU使用率过高如何排查。之前他们问过生产环境不能重启数据库的情况下如何监控内存分配,现在转向CPU的问题,可能他们正在面临性能问题,需要快速定位原因。作为技术支持,我需要提供一套系统化的排查方法,确保用户能在不重启数据库的情况下找到问题根源。 首先,我得回忆一下常见的CPU过高的原因。通常,CPU高可能是因为查询效率低下,比如全表扫描、缺少索引、复杂连接操作,或者锁竞争、大量并发连接,甚至配置不当,比如缓冲区设置不合理。还有可能是硬件资源不足,比如CPU本身不够用。 接下来,我需要考虑用户可能的使用场景。用户是在生产环境,不能重启数据库,所以任何需要重启的调整都不适用。需要提供实时监控和动态调整的方法。用户可能没有root权限,或者只能通过SQL访问,所以需要分层次的解决方案,既有SQL层面的查询,也有系统命令,可能还有需要管理员权限的工具。 接下来,我需要组织回答的结构。通常,排查步骤应该从快速检查开始,逐步深入。比如先确认当前负载,然后检查慢查询,分析当前活动会话,查看锁情况,检查配置,最后系统级分析。可能还需要考虑复制延迟、存储引擎问题等。 需要确保提到的工具和命令都是可以在线执行的,不需要重启。比如使用SHOW PROCESSLIST、启用Performance Schema,使用sys schema,或者系统工具如top、perf、pt-query-digest等。还要注意权限问题,比如某些系统命令可能需要sudo,但用户可能没有权限,所以需要提供替代方案。 可能用户对某些工具不熟悉,需要给出具体的命令示例,比如如何启用Performance Schema的监控项,如何分析慢查询日志,如何使用pt-query-digest工具。同时要提醒注意事项,比如开启监控对性能的影响,特别是在高负载时。 还要考虑用户可能需要紧急处理,比如如何快速终止有问题的会话,或者调整某些变量来缓解问题,比如调整线程池大小或连接数限制,但要注意这些调整可能需要权限,并且临时生效还是永久生效的问题。 另外,可能需要解释一些术语,比如缓冲池命中率、锁等待,但用户之前可能已经了解过内存监控,所以可能有一定基础,可以适当使用术语,但保持解释清晰。 最后,总结一个排查流程图或表格,帮助用户根据不同的场景选择合适的工具和方法,比如如果是慢查询导致,就检查慢日志;如果是锁竞争,就查看锁信息等。还要提醒用户长期优化的建议,比如定期分析慢查询,优化索引,调整配置参数等。 需要确保回答结构清晰,分步骤,每个步骤有具体的操作和示例命令,同时给出可能的原因和解决方案。还要注意安全性,比如在终止会话前确认是否为问题会话,避免误操作影响生产环境。</think>--- ### MySQL CPU使用率过高排查指南(无需重启) --- #### 一、快速定位问题方向 **1. 确认CPU负载类型** ```bash # 查看CPU使用分布(用户态 vs 内核态) top -c -p $(pidof mysqld) ``` - **用户态CPU高**:通常由SQL执行(如全表扫描、排序、复杂JOIN)导致 - **内核态CPU高**:可能涉及锁竞争、I/O等待或网络问题 **2. 检查当前活动线程** ```sql -- 查看正在执行的SQL(实时快照) SHOW PROCESSLIST; -- 或使用sys Schema增强版视图 SELECT * FROM sys.processlist WHERE command != 'Sleep' ORDER BY time DESC; ``` --- #### 二、核心排查步骤 ##### 1. **抓取高消耗SQL** **方法1:开启慢查询日志(动态配置)** ```sql -- 临时开启慢日志(无需重启) SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- 捕获超过1秒的查询 SET GLOBAL log_queries_not_using_indexes = ON; -- 确认日志路径 SHOW VARIABLES LIKE 'slow_query_log_file'; ``` **方法2:使用Performance Schema(MySQL 5.6+)** ```sql -- 启用事件监控 UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements%'; -- 查看CPU时间Top10的SQL SELECT DIGEST_TEXT, SUM(CPU_TIME)/1000000 AS cpu_sec, COUNT_STAR AS exec_count FROM performance_schema.events_statements_summary_by_digest ORDER BY cpu_sec DESC LIMIT 10; ``` ##### 2. **分析锁竞争** ```sql -- 查看当前锁等待 SELECT * FROM sys.innodb_lock_waits; -- 检查行锁冲突 SHOW ENGINE INNODB STATUS\G -- 关注 "TRANSACTIONS" 和 "LATEST DETECTED DEADLOCK" 部分 -- 查看表级锁 SHOW OPEN TABLES WHERE In_use > 0; ``` ##### 3. **检查配置与资源** ```sql -- 关键参数检查 SHOW VARIABLES LIKE 'innodb_thread_concurrency'; -- 并发线程限制 SHOW VARIABLES LIKE 'tmp_table_size'; -- 临时表内存阈值 SHOW STATUS LIKE 'Threads_running'; -- 当前活跃线程数 -- 缓冲池命中率(低于99%需警惕) SELECT (1 - (Variable_value / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads))) * 100 AS hit_rate FROM (SELECT VARIABLE_VALUE AS Innodb_buffer_pool_read_requests FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') a, (SELECT VARIABLE_VALUE AS Innodb_buffer_pool_reads FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads') b; ``` --- #### 三、系统级诊断工具 ##### 1. **perf 火焰图定位热点函数** ```bash # 安装perf sudo apt-get install linux-perf # Ubuntu sudo yum install perf # CentOS # 采集MySQL进程CPU使用(采样30秒) sudo perf record -F 99 -p $(pidof mysqld) -g -- sleep 30 sudo perf script > out.stack # 使用FlameGraph生成火焰图 git clone https://github.com/brendangregg/FlameGraph ./FlameGraph/stackcollapse-perf.pl out.stack | ./FlameGraph/flamegraph.pl > cpu.svg ``` ##### 2. **pt-query-digest 分析SQL** ```bash # 分析慢查询日志 pt-query-digest /var/lib/mysql/slow.log # 实时分析tcpdump流量(需权限) tcpdump -i eth0 -s 65535 -w - port 3306 | pt-query-digest --type tcpdump ``` --- #### 四、常见问题与应急处理 | 现象 | 快速验证方法 | 临时解决方案 | |-----------------------|----------------------------|--------------------------| | 全表扫描过多 | `EXPLAIN`查看执行计划 | 添加缺失索引 | | 排序操作消耗大 | 检查`Sort_merge_passes`状态 | 增大`sort_buffer_size` | | 大量临时表到磁盘 | 监控`Created_tmp_disk_tables`| 增大`tmp_table_size` | | 锁等待严重 | `SHOW ENGINE INNODB STATUS`| 终止阻塞事务(`KILL [ID]`)| **紧急降负操作:** ```sql -- 限制最大连接数(动态调整) SET GLOBAL max_connections = 50; -- 关闭查询缓存(如果启用) SET GLOBAL query_cache_size = 0; -- 终止高消耗会话 SELECT id, time, info FROM information_schema.processlist WHERE command != 'Sleep' ORDER BY time DESC; KILL [problematic_thread_id]; ``` --- #### 五、长期优化建议 1. **索引优化** - 使用`pt-index-usage`分析索引有效性 - 定期运行`ANALYZE TABLE`更新统计信息 2. **架构调整** - 读写分离(使用MySQL Router或ProxySQL) - 热点数据拆分(分库分表) 3. **监控体系** ```bash # 推荐监控组合 Prometheus + Grafana + mysqld_exporter # 资源监控 Percona Monitoring and Management (PMM) # 专业MySQL监控 ``` --- ### 排查流程图 ``` CPU高负载 → 检查用户态/内核态 → ├─用户态高 → 分析慢查询/执行计划 → 优化SQL或索引 ├─内核态高 → 检查锁竞争/I/O → 调整事务隔离级别/优化磁盘 └─系统级问题 → 使用perf火焰图 → 定位代码层问题 ``` 通过以上方法,可在不重启数据库的情况下精准定位CPU问题根源。对于复杂场景,建议结合多种工具交叉验证。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值