MYSQL 查询select、更新update导致CPU占用高

 

线上的某个服务保存操作很慢,备份服务器连备份数据库很快,但备份服务器连接该数据库也很慢,可以确定是数据库的问题。

通过监控发现,一执行 SQL 语句 CPU 占用就飙升至 100%,再看慢查询日志,都是很简单 SQL,也很慢。

 

原因是:查询的表没有设置主键和索引,而表中又有 blob 字段。该字段随着服务的使用存储了越来越多的数据,导致查询慢。

 

为什么 blob 字段在没有主键以及索引的情况下会慢呢?

 

实际上,根本原因是因为 MySQL 是行数据库,而主键、索引只是一种优化。

举个栗子,现在有一个 10W 行的 table,有3个字段:path(varchar)、content(blob)、lastmodified(timestamp),3个都不是主键、索引,也都不符合非空唯一的条件[1]。

执行 select * from table where path = 'a/b/c/d'; MySQL必须把10W行的 path 都取出来(path不唯一的话)一一判断。

由于是行数据库,每一行的 content 和 lastmodified 也会被取出来,即使没有用到。

索引的存在可以优化这个问题, B+ 树的叶子节点存储真实数据,非叶子节点存储索引数据。当 SQL 语句用到了索引时,从 B+ 树的根结点(实际上也可从叶节点开始)进行遍历,满足索引条件后,再去拿出真实数据判断非索引列的条件,最终得出结果。这也是为什么在 WHERE 后要先写索引列再写非索引列的原因。

 

解决办法:

按照上面的说法,

根本解决办法是:新建一个表存储 blob 字段,通过一个唯一字段与原表关联。

优化的办法是:建立主键或索引,并在查询时尽量使用到。

 

[1]对于没有设置主键的表,MySQL会寻找第一个非空唯一列默认作为主键,如果没有符合条件的列(我就是这种情况),会自动增加一列6字节的隐藏列作为自增主键。参考:

If you do not define a PRIMARY KEY for your table, MySQL picks the first UNIQUE index that has only NOT NULL columns as the primary key and InnoDB uses it as the clustered index. If there is no such index in the table, InnoDB internally generates a clustered index where the rows are ordered by the row ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order. 

 

<think>好的,我现在需要帮助用户排查MySQL服务CPU占用的问题。首先,我应该回忆一下常见的导致MySQLCPU使用率的原因,然后一步步指导用户进行排查。根据用户提供的引用内容,特别是引用[3]中提到了LNMP架构和phpMyAdmin的配置,可能涉及到数据库查询优化的问题。 首先,用户需要确认CPU使用率是否确实由MySQL引起。可以通过top或htop命令查看进程,确认mysqld进程是否占用了较CPU资源。接着,检查MySQL的运行状态,使用SHOW PROCESSLIST查看当前执行的查询,找出是否有长时间运行或阻塞的查询。 然后,考虑慢查询的问题。用户可能没有开启慢查询日志,需要指导他们如何设置,然后分析日志中的查询,进行优化。索引缺失也是一个常见问题,使用EXPLAIN分析查询执行计划,查看是否缺少合适的索引。 此外,还需要检查是否存在锁争用,比如表锁或行锁,这可能导致查询堆积,增加CPU负担。内存不足也可能导致频繁的磁盘I/O,间接增加CPU负载。用户可能需要调整InnoDB缓冲池大小,确保足够的内存用于缓存数据。 另外,引用[2]提到了缓存库如cache2k、Caffeine,可能用户的应用中使用了缓存,但如果缓存配置不当,可能导致大量查询直接打到数据库,增加CPU负担。需要检查应用层的缓存策略,确保有效利用缓存减少数据库压力。 最后,建议用户进行硬件和系统层面的检查,比如CPU使用率是否持续,是否存在其他进程竞争资源,或者MySQL配置参数是否需要优化,如连接数设置过导致线程频繁切换。 总结下来,步骤大致是:确认MySQLCPU消耗源,检查当前查询,分析慢查询,优化索引,处理锁争用,调整内存配置,检查应用层缓存,最后系统级优化。需要一步步引导用户排查,确保每个环节都考虑到可能的因素,并提供相应的命令或配置方法供用户操作。</think>### MySQL服务CPU占用的排查步骤 #### 1. **确认CPU使用情况** - **检查进程**:使用`top`或`htop`命令,确认是否是`mysqld`进程占用CPU。例如: ```bash top -c -p $(pgrep mysqld) ``` - **系统监控**:通过`vmstat`或`mpstat`分析CPU使用分布(用户态、内核态、I/O等待等)。 #### 2. **分析MySQL内部状态** - **查看活跃线程**: ```sql SHOW FULL PROCESSLIST; ``` 关注`State`列中`Sending data`、`Sorting result`、`Creating tmp table`等消耗操作[^3]。 - **检查锁争用**: ```sql SHOW ENGINE INNODB STATUS; ``` 查看`TRANSACTIONS`部分是否有事务阻塞,或`LATEST DETECTED DEADLOCK`死锁记录。 #### 3. **优化查询性能** - **启用慢查询日志**: ```sql SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2; -- 定义慢查询阈值(秒) ``` 日志路径通常在`/var/lib/mysql/[hostname]-slow.log`。 - **分析慢查询**: 使用`mysqldumpslow`或`pt-query-digest`工具解析日志,找出频或耗时的SQL语句。 - **使用`EXPLAIN`分析执行计划**: ```sql EXPLAIN SELECT * FROM table WHERE condition; ``` 关注`type`(扫描类型)、`rows`(扫描行数)、`Extra`(是否使用临时表或文件排序)。 #### 4. **索引优化** - **检查缺失索引**: ```sql SELECT * FROM sys.schema_unused_indexes; ``` 删除冗余索引,减少维护开销。 - **添加复合索引**:根据`WHERE`和`ORDER BY`条件创建覆盖索引。例如: ```sql ALTER TABLE orders ADD INDEX idx_customer_status (customer_id, status); ``` #### 5. **配置调优** - **调整缓冲池大小**(InnoDB): ```sql SET GLOBAL innodb_buffer_pool_size = 2G; -- 建议为物理内存的50%-70% ``` - **优化线程池**: 避免连接数过导致上下文切换频繁。检查`max_connections`和`thread_cache_size`参数。 #### 6. **排查外部因素** - **应用层缓存**:检查是否因缓存失效(如引用[2]中的`cache2k`、`Caffeine`)导致大量查询直接访问数据库。 - **批量操作**:确认是否有大量`INSERT/UPDATE`语句未批量提交,或锁范围过大。 #### 7. **硬件与系统层面** - **磁盘I/O**:使用`iostat`检查磁盘负载,若I/O等待,考虑升级SSD或优化写入策略。 - **内存不足**:若`InnoDB`缓冲池命中率低(通过`SHOW STATUS LIKE 'Innodb_buffer_pool_read%'`计算),需增加内存。 --- ### 示例命令与输出解析 ```sql -- 查看当前运行时间最长的查询 SELECT * FROM information_schema.processlist WHERE TIME > 60 ORDER BY TIME DESC LIMIT 5; ``` 输出中的`TIME`列显示查询已执行时间(秒),`INFO`列显示具体SQL片段。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值