我在 Debian Squeeze 64 上遇到了 mysql 占用 CPU 的问题。这是一台 VPS 上的开发机器,所以我停止了所有其他服务,包括 apache2。mysql 版本是 5.1.49。这是 mysql 启动时的日志:
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld_safe: Starting mysqld daemon with databases from /var/lib/mysql
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: 130206 19:03:40 [Note] Plugin 'FEDERATED' is disabled.
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: InnoDB: 1 transaction(s) which must be rolled back or cleaned up
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: InnoDB: in total 1 row operations to undo
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: InnoDB: Trx id counter is 0 31809536
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: 130206 19:03:40 InnoDB: Started; log sequence number 2 892018402
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: 130206 19:03:40 [Note] Event Scheduler: Loaded 0 events
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: 130206 19:03:40 [Note] /usr/sbin/mysqld: ready for connections.
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: Version: '5.1.49-3-log' socket: '/var/run/mysqld/mysqld.sock' port: 3306 (Debian)
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: InnoDB: Starting in background the rollback of uncommitted transactions
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: InnoDB: Cleaning up trx with id 0 2218455
Feb 6 19:03:40 Debian-60-squeeze-64-LAMP mysqld: 130206 19:03:40 InnoDB: Rollback of non-prepared transactions completed
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4616]: Upgrading MySQL tables if necessary.
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4619]: /usr/bin/mysql_upgrade: the '--basedir' option is always ignored
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4619]: Looking for 'mysql' as: /usr/bin/mysql
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4619]: Looking for 'mysqlcheck' as: /usr/bin/mysqlcheck
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4619]: This installation of MySQL is already upgraded to 5.1.49, use --force if you still need to run mysql_upgrade
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4626]: Checking for insecure root accounts.
Feb 6 19:03:41 Debian-60-squeeze-64-LAMP /etc/mysql/debian-start[4630]: Triggering myisam-recover for all MyISAM tables
我启动 mysql 的那一刻,尽管没有正在运行的查询,但 CPU 却飞涨。这是 /etc/init.d/mysql status 的输出:
Server version 5.1.49-3-log
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /var/run/mysqld/mysqld.sock
Uptime: 29 min 38 sec
Threads: 1 Questions: 955 Slow queries: 0 Opens: 5512 Flush tables: 1 Open tables: 32 Queries per second avg: 0.537.
对占用 100% CPU 的 mysql pid 使用 strace 后,我只用了 1 到 2 分钟就得到了如下结果:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
90.89 126.423901 179579 704 select
4.01 5.572348 2786174 2 rt_sigtimedwait
2.99 4.164260 118979 35 1 futex
2.11 2.929960 1 3471808 gettimeofday
0.00 0.000000 0 3 1 read
0.00 0.000000 0 3 write
0.00 0.000000 0 1 close
0.00 0.000000 0 4 rt_sigprocmask
0.00 0.000000 0 1 1 access
0.00 0.000000 0 6 sched_yield
0.00 0.000000 0 1 alarm
0.00 0.000000 0 1 accept
0.00 0.000000 0 1 shutdown
0.00 0.000000 0 1 getsockname
0.00 0.000000 0 2 1 setsockopt
0.00 0.000000 0 7 fcntl
0.00 0.000000 0 1 tgkill
------ ----------- ----------- --------- --------- ----------------
100.00 139.090469 3472581 4 total
实际调用如下所示:
19:37:26.553922 gettimeofday({1360175846, 553939}, NULL) = 0 <0.000004>
19:37:26.622537 gettimeofday({1360175846, 622591}, NULL) = 0 <0.000011>
19:37:26.622659 gettimeofday({1360175846, 622679}, NULL) = 0 <0.000009>
19:37:26.622737 gettimeofday({1360175846, 622754}, NULL) = 0 <0.000009>
19:37:26.622812 gettimeofday({1360175846, 622829}, NULL) = 0 <0.000008>
19:37:26.622887 gettimeofday({1360175846, 622951}, NULL) = 0 <0.000010>
19:37:26.623010 gettimeofday({1360175846, 623028}, NULL) = 0 <0.000008>
19:37:26.623109 gettimeofday({1360175846, 623132}, NULL) = 0 <0.000009>
我估计问题出在对 gettimeofday 的 3471808 次调用上,但我该如何修复它呢?每次启动 mysql 时都会发生这种情况,我甚至尝试过重新启动服务器。
谢谢 !
根据要求提供其他信息:
SHOW PROCESSLIST 的输出
mysql> SHOW PROCESSLIST;
+-----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+------+-----------+------+---------+------+-------+------------------+
| 325 | root | localhost | NULL | Query | 0 | NULL | SHOW PROCESSLIST |
+-----+------+-----------+------+---------+------+-------+------------------+
1 row in set (0.00 sec)
top -H 的输出:
top - 21:21:26 up 5:35, 2 users, load average: 1.07, 1.02, 1.00
Tasks: 152 total, 2 running, 150 sleeping, 0 stopped, 0 zombie
Cpu(s): 96.2%us, 1.9%sy, 0.0%ni, 0.0%id, 0.0%wa, 1.9%hi, 0.0%si, 0.0%st
Mem: 2061536k total, 973540k used, 1087996k free, 44952k buffers
Swap: 2102552k total, 0k used, 2102552k free, 693716k cached
答案1
我没有其他办法,所以最后我不得不重新安装 mysql 服务器,这解决了这个问题,从备份恢复数据库后,现在一切都运行顺利。
答案2
我遇到过类似的问题,Debian Squeeze(32 位)上的 MySQL 5.1 有时(并非总是如此)会达到 100% CPU,但我没有时间对其进行诊断,因为这距离关键截止日期还有几天。
细节
我发现有几种不同的方法可以解决 MySQL 中的高 CPU 问题。
最简单的重现方法是运行特定的 Django 管理视图(标准管理 UI 页面),该视图会连接几个表并返回几千行 - 这会使一个线程可靠地占用 99% 的 CPU。终止该线程即可解决问题。
mysql> show processlist;
+----+------------+-----------+-----------+---------+------+------------+-------------------------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------------+-----------+-----------+---------+------+------------+-----------------------------------------------------------------------------------------------------+
| 68 | djangouser | localhost | django_db | Query | 77 | statistics | SELECT `mytable`.`id`, `mytable`.`tenant_id`, `mytable |
| 69 | djangouser | localhost | django_db | Query | 0 | NULL | show processlist |
+----+------------+-----------+-----------+---------+------+------------+------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
有关的
https://groups.google.com/forum/?fromgroups=#!topic/django-users/Iz6x7c0i9nI与 Django 查询集中发生挂起的情况非常相似。
类似情况:
https://dba.stackexchange.com/questions/24643/mysql-5-5-runs-out-of-memory-drops-all-connections-when-creating-many-databasesdba.stackexchange - MySQL 在创建 2,000 到 5,000 个数据库后断开所有连接
https://groups.google.com/forum/?fromgroups=#!topic/django-users/sU-zj7s8uU4- 由于 20 个内部连接,某些 Django 管理查询上的查询优化器无法终止!修复方法是将 optimizer_search_depth 设置为 3(默认值为 62)
我的解决方案 - 切换到 PostgreSQL
Django 使得仅通过配置即可轻松切换到 PostgreSQL,再加上安装和配置 PostgreSQL 的时间 - 我意识到这可能不适合你,但如果你的语言/框架可以轻松切换,请认真考虑一下。我使用了 Debian 6.0 Squeeze 中的默认 postgres 包,它们很好 - 或者你可以使用 Postgres 项目中的 Debian 9.1 或 9.2 包,它们可能更好,而且更新得多。
尽管我之前没有用过 PostgreSQL,但转换过程只花了几个小时,解决了这个问题,没有产生新的问题。而且 PostgreSQL 还有许多其他不错的功能,因此我现在非常高兴我转换了 PostgreSQL。
到目前为止,我对 MySQL 和 PostgreSQL 还没有强烈的看法,但现在我只会使用后者。
答案3
我遇到了同样的问题。这是由于拼写错误造成的,而不是:
innodb_buffer_pool_size = 256M
我写
innodb_buffer_pool_size = 256M