使用云数据库 MySQL 版时,如果实例的 CPU 使用率过高或接近 100%,可能会导致数据读写处理缓慢、连接延迟加剧,甚至在删除操作时出现错误,从而严重影响业务的正常运行。本文中提供了几种常见原因的定位以及解决方法。
查看 CPU 使用率的监控项,确认实例当前的 CPU 使用率。
在实例列表页面,单击目标实例的实例名称,进入实例信息页。
在页面上方,单击监控告警页签。
在资源监控分类下,查看 CPU使用率。
说明
可按照节点维度查看实例各节点的 CPU 使用率
如果 CPU 使用率已经非常接近 100%,可以通过以下两种手段快速恢复实例性能。
注意
重启实例的耗时取决于实例的负载状态,会导致业务有 1~2 次闪断,请谨慎操作。建议您增加应用的重连机制,可以大幅降低数据库连接闪断对业务的影响。
在实例列表页面,单击目标实例操作列的 … > 重启实例。
在弹出的对话框中,分别选择重启范围为所有节点、重启时间为立即重启后,单击确定。
说明
可按照节点维度查看实例各节点的 CPU 使用率。如果 CPU 使用率过高的节点为主节点,重启范围应为所有节点;如果 CPU 使用率过高的节点为某个只读节点,重启范围应为指定只读节点,并在只读节点下拉列表中选择相应只读节点。
说明
更多详细信息,请参见重启实例。
说明
切换主节点期间数据库将有 1~2 次闪断,请谨慎操作,同时建议您增加应用程序的重连机制。
在实例列表页面,单击目标实例名称,进入实例信息页签。
单击连接管理页签,在实例拓扑区域,将鼠标指针指向备节点,在弹出的窗口中单击切换主节点,在弹出的对话框中单击确定,即可完成主备节点的切换。
说明
更多详细信息,请参见切换主节点。
原因分析
TP 系统 SQL 执行一般比较快,MySQL 实例的 CPU 不会在没有负载的情况下无故升高,大多数 CPU 使用率升高是由于异常的 SQL 负载导致资源被过度消耗。因此要首先确认是否流量发生了变化、是否上线了新的 SQL。具体方式是在数据库工作台查看实例的总查询数监控项。
操作路径:登录 数据库工作台 > 观测诊断 > 性能监控 > 总查询数。更详细信息,请参见查看性能监控指标。
解决办法
通过数据库工作台的慢日志分析和全量 SQL 洞察功能确定是哪些 SQL 引起的 CPU 负载升高,并通过 SQL 限流来限制 SQL 的执行频率,防止异常负载打满 CPU。
说明
全量 SQL 洞察和 SQL 限流当前为数据库工作台的邀测功能,如需使用请提交工单申请。
定位 SQL
慢日志分析
进行慢日志分析的操作路径:登录 数据库工作台 > 观测诊断 > 慢日志分析。更详细信息,请参见慢日志分析。
进行慢日志分析时,可以重点关注以下信息:
平均锁等待时间 判断慢 SQL 是 off-CPU 多还是 on-CPU 多。等待时间长说明 SQL 长时间不占用 CPU,反之则证明 on-CPU 时间多。
平均扫描行数 一般与跟 CPU 使用率正相关。
重点关注Rows_examined
字段,如果很高说明需要消耗更多资源扫描行数会占用更多 CPU 资源。
# Time: 2022-12-14T15:01:34.892085Z # User@Host: root[root] @ localhost [] Id: 8 # Query_time: 3.985637 Lock_time: 0.000138 Rows_sent: 165346 Rows_examined: 9900000 Thread_id: 8 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 4848540 Read_first: 0 Read_last: 0 Read_key: 1 Read_next: 9900000 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Start: 2022-12-14T15:01:30.906448Z End: 2022-12-14T15:01:34.892085Z Schema: slow Rows_affected: 0 SET timestamp=1671030090;SELECT * FROM `student` WHERE id>100000 AND `name`='Yunxi';
SQL 洞察
进行 SQL 洞察的操作路径:登录数据库工作台 > 观测诊断 > 全量 SQL 洞察。更详细信息,请参见全量 SQL 洞察。
进行 SQL 洞察时,可关注 TotalExecTime,其表示一段时间内执行 SQL 的耗时,可对其进行降序排序,定位到耗时最多的 SQL。
处理 SQL
定位到 SQL 后,可通过 SQL 限流或 KILL 会话的方式进行处理。
SQL 限流
定位到问题 SQL 后,可以通过 SQL 限流限制 SQL 的执行频率。
操作路径:
KILL 会话
原因分析
逻辑读数量与 CPU 消耗一般正相关,如果逻辑读数量增加,基本可以确认 CPU 使用率升高与 SQL 有关,而不是数据库的环境发生了变化,可以通过查看以下监控项确认读取行数和 CPU 使用率的相关性。
InnoDB 读取量
InnoDB 平均每秒从 BufferPool 读取页的次数(逻辑读)
解决办法
执行 show processlist
命令,或通过数据库工作台的慢日志分析和全量 SQL 洞察确定是哪些 SQL 引起的 CPU 负载升高,并通过 KILL SQL 或 SQL 限流的方式来解决。KILL SQL 的方式如下:
查看正在运行的事务,看是否有长时间运行的 SQL。
mysql> select * from information_schema.innodb_trx \G; *************************** 1. row *************************** trx_id: 1335 trx_state: LOCK WAIT trx_started: 2023-12-28 17:36:35 trx_requested_lock_id: 1335:25:3:2 trx_wait_started: 2023-12-28 17:45:31 trx_weight: 2 trx_mysql_thread_id: 7432 # 跟processlist的ID是同一个值 trx_query: update t1 set c2 = c2 + 200 where c1 = 1 trx_operation_state: starting index read trx_tables_in_use: 1 trx_tables_locked: 1 trx_lock_structs: 2 trx_lock_memory_bytes: 1160 trx_rows_locked: 3 trx_rows_modified: 0 trx_concurrency_tickets: 0 trx_isolation_level: REPEATABLE READ trx_unique_checks: 1 trx_foreign_key_checks: 1 trx_last_foreign_key_error: NULL trx_adaptive_hash_latched: 0 trx_adaptive_hash_timeout: 0 trx_is_read_only: 0 trx_autocommit_non_locking: 0
执行 KILL 命令,防止该 SQL 继续消耗 CPU。使用的 ID 是 processlist 中的 ID。
mysql> KILL 7432 -- from processlist
优化 SQL,减少逻辑读。对于扫描行数过多但是不好优化的 SQL,可以通过添加索引来提升过滤性。
导致执行计划错误的原因有两种,一种是统计数据滞后,另一种是优化器问题。
统计数据滞后
原因分析
MySQL 会自动更新表统计信息来帮助优化器选择适合的 access path,如果统计信息不准确,优化器的判断可能受到影响;如实际行数远大于统计信息的行数,优化器可能会认为全表扫描效率更高从而导致执行计划错误,扫描过多行导致 CPU 使用率升高。执行以下命令查看统计信息,可判断统计数据是否有滞后。
select * from innodb_table_stats where database_name='' and table_name='';
解决办法
不要依赖 MySQL 定时更新统计信息的机制,对频繁修改的大表进行统计数据评估,查看mysql.innodb_table_stats
的 last_update
字段即可。对于长期没有更改的统计数据进行重点关注,并在低峰期手动 analyze table
更新统计信息。
优化器问题
原因分析
使用 order by limit 导致统优化器判断不准使用了全表扫描。
解决办法
查看优化器参数 select @@optimizer_switch\G
,尝试关闭问题优化器参数,如prefer_ordering_index
。
FORCE INDEX 指定索引。
原因分析
如果配置的并发数超过了当前配置的合理值,导致 MySQL 活跃线程数高,那么在并发上升时,MySQL 可能因为活跃线程数过多而发生「塞车」,导致 CPU 使用率增加。可以通过查看监控项运行线程数确认读取行数和 CPU 使用率的相关性。
操作路径:登录 数据库工作台 > 观测诊断 > 性能监控 > 运行线程数。更详细信息,请参见查看性能监控指标。
解决办法
控制 server 层并发,关注 thread_pool_size
* thread_pool_oversubscribe
的值,这两个参数乘积为最多允许的活跃线程数,经验值为不要超过CPU核心数的2-3倍
控制 innodb 层并发,配置 innodb_thread_concurrency
。
及时升级内核版本。如有需要,请提交工单联系技术支持进行升级。
原因分析
云数据库 MySQL 版默认采用的是 Read-Committed(RC) 隔离级别,但允许用户设置为 Repeatable-Read(RR)级别。在 RR 级别下有可能会有 RC 隔离级别下没有的 CPU 使用率升高的问题。
解决办法
确认 RR 是否是为需要的隔离级别,如果不是可以调整为RC
如果历史链表长造成扫描量上升可以配置 auto kill,kill 掉执行时间过长的 SQL。
经过以上手段进行排查和解决后,如果 CPU 使用率仍持续升高,则可能是业务压力导致的正常情况,此时可考虑通过常规变配或临时升配提高实例规格,增加 CPU 核数可降低实例压力。
关于如何对实例进行常规变配或临时升配,请参见以下文档:
说明
临时升配当前为云数据库 MySQL 版的邀测功能,如需使用,请提交工单申请。