文章目录
- 一、分析思路
- 二、详细分析方法
- 1、排除本机自身原因
- 2、服务器性能分析
- (1)查看服务器的内存和服务器核数大小
- (2)服务器的负载
- 3、虚拟机分析
- 4、数据库分析(MySql)
- (1)进程列表
- (2)最大连接数
- (3)连接超时
- (3)DNS反向解析
- (4)表高速缓存
- (5)慢查询日志
一、分析思路
- 排除本机自身原因
- 服务器性能分析
- 虚拟机分析
- 数据库分析
二、详细分析方法
1、排除本机自身原因
查看服务器的网络情况可以下载一个大型文件基本就可以确定网络情况了。或者使用站长工具测试网站速度。
2、服务器性能分析
(1)查看服务器的内存和服务器核数大小
①查看服务器内存大小
cat /proc/meminfo | grep MemTotal
②查看服务器核数
总核数 = 物理CPU个数 * 每个物理CPU的核数
查看CPU的个数:
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
查看每个CPU中core的个数
cat /proc/cpuinfo| grep "cpu cores"| uniq
(2)服务器的负载
在确定CPU的内存和CPU核数后,就可以进一步观察服务器的负载
Linux的负载高,主要是由于 CPU使用、内存使用 引起的。其中任何一项的急剧增加,都会使得服务器的负载急剧升高
使用top命令查看服务器的资源使用情况,主要分析CPU和内存的使用情况(top 命令是 Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,默认5秒刷新一下进程列表,所以类似于 Windows 的任务管理器。)
第一行:
top - 14:50:58 up 16:46, 2 users, load average: 1.15, 0.63, 0.44
- 14:50:58:系统当前时间
- up 16:46 :系统开机到现在经过了2天
- 2 users:当前1用户在线
- load average: 1.15, 0.63, 0.44:系统1分钟、5分钟、15分钟的CPU负载信息.
备注:load average后面三个数值的含义是最近1分钟、最近5分钟、最近15分钟系统的负载值。这个值的意义是,单位时间段内CPU活动进程数。如果你的机器为单核,那么只要这几个值均<1,代表系统就没有负载压力,如果你的机器为N核,那么必须是这几个值均<N才可认为系统没有负载压力。
CPU利用率:显示的是程序在运行期间实时占用的CPU百分比;
第二行解释:
Tasks: 147 total, 1 running, 146 sleeping, 0 stopped, 0 zombie
- 147 total,:当前有108个任务
- 1 running:1个任务正在运行
- 46 sleeping,:107个进程处于睡眠状态
- 0 stopped:停止的进程数
- 0 zombie:僵死的进程数
第三行解释:
Cpu(s): 1.7%us, 0.2%sy, 0.0%ni, 95.6%id, 2.3%wa, 0.1%hi, 0.1%si, 0.0%st
- 1.7%us:用户态进程占用CPU时间百分比
- 0.2%sy,:内核占用CPU时间百分比
- 0.0%ni:renice值为负的任务的用户态进程的CPU时间百分比。nice是优先级的意思
- 95.6%id:空闲CPU时间百分比
- 2.3%wa:等待I/O的CPU时间百分比
- 0.1%hi:CPU硬中断时间百分比
- 0.1%si:CPU软中断时间百分比
第四行解释:
Mem: 32959108k total, 32783520k used, 175588k free, 291084k buffers
- 32959108k total:物理内存总数
- 32783520k used: 使用的物理内存
- 175588k free:空闲的物理内存
- 291084k buffers:用作缓存的内存
第五行解释:
Swap: 4194296k total, 148k used, 4194148k free, 10365856k cached
- 4194296k total:交换空间的总量
- 148k used: 使用的交换空间
- 4194148k free:空闲的交换空间
- 10365856k cached:缓存的交换空间
我个人的理解是:当us的百分比小于50%时,是不需要去考虑服务器的配置问题的,如果服务器的us百分比长时间在70%以上时,可以考虑加强服务器的硬件配置。
3、虚拟机分析
使用top指令查看虚拟机的内存占用情况,有时候可以发现虽然虚拟机占用内存的百分比不大却有明显的上限值,我们就需要去查看虚拟机的配置情况。
解决方法(以tomcat为例):
具体的数值根据实际情况而定。
4、数据库分析(MySql)
(1)进程列表
排除高并发因素先要找到导致CPU过高的SQL
mysql> SHOW PROCESSLIST;
查找负荷最重的SQL语句,优化该SQL,比如适当建立某字段的索引。+----+------+-----------------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------------+------+---------+------+-------+------------------+
| 11 | root | localhost:56919 | test | Query | 0 | NULL | SHOW PROCESSLIST |
+----+------+-----------------+------+---------+------+-------+------------------+
1 row in set
字段 | 描述 |
---|---|
Id | 进程标识,Kill时使用。 |
User | 当前用户权限范围内的SQL语句 |
Host | 从哪个IP的端口发出的,用来追踪出问题语句的用户。 |
db | 进程目标连接的是哪个数据库 |
Command | 显示当前连接执行的命令:休眠sleep/查询query/连接connect/ |
Time | 状态持续时间秒数 |
State | 使用当前连接的SQL语句的状态 |
Info | 显示SQL语句 |
休眠的线程
一般而言,休眠Sleep连接过多会严重消耗MySQL服务器资源(CPU和内存),可能会导致MySQL崩溃。
临时文件大小
若进程列表中出现大量Copying to tmp table on disk状态
,则明显是由于临时表过大导致MySQL将临时表写入磁盘而影响了整体性能。可通过调整tmp_table_size临时表大小来解决,MySQL中tmp_table_size
默认是16MB。
mysql> SHOW VARIABLES LIKE "%tmp_table_size%";
+----------------+----------+
| Variable_name | Value |
+----------------+----------+
| tmp_table_size | 18874368 |
+----------------+----------+
1 row in set
临时设置临时表大小
mysql> SET GLOBAL tmp_table_size=33554432;
(2)最大连接数
查看MySQL连接数,看看是否超过了MySQL设置的连接数。
show variables like '%max_connections%'; 查看最大连接数
show status like 'Threads%'; 当前连接的使用情况
-
Threads_connected—打开的连接数
-
Threads_running—这个数值指的是激活的连接数,这个数值一般远低于connected数值
如果最大连接数的值太小可以根据实际情况进行修改,一般修改为1000即可,设置方法有两种:
-
临时设置,重启服务后将失效
-
修改数据库配置文件
在/etc/my.cnf 文件的[mysqld]下增减一行: max_connections = 1000
(3)连接超时
wait_timeout用于设置SQL语句睡眠连接超时秒数,若连接超时则会被MySQL自然终止。
如果wait_timeout设置过大MySQL中会存在大量的SLEEP进程无法及时释放,会拖累系统性能。若wait_timeout过小,可能会遭遇MySQL has gone away之类的问题。通常而言,wait_timeout设置为10个小时是最佳选择。
MySQL默认wait_timeout为28800秒即8小时,意味着一个连接的空闲时间若超过8小时则会自动断开连接,然后连接池却认为该连接还是有效的。
mysql> SHOW VARIABLES LIKE "%wait_timeout%";
+--------------------------+----------+
| Variable_name | Value |
+--------------------------+----------+
| innodb_lock_wait_timeout | 50 |
| lock_wait_timeout | 31536000 |
| wait_timeout | 28800 |
+--------------------------+----------+
3 rows in set
(3)DNS反向解析
MySQL数据库收到一个网络连接后,首先拿到对方的IP地址,然后对这个IP地址进行反向DNS解析从而得到这个IP地址对应的主机名。用主机名在权限系统里面进行权限判断。反向DNS解析是耗费时间的,有可能让用户感觉起来很慢。甚至有的时候,反向解析出来的主机名并没有指向这个IP地址,这时候就无法连接成功了。 可以在配置文件里面禁止MySQL进行反向DNS解析,只需在my.cnf的[mysqld]段落中加入如下行即可:
skip-name-resolve (windows与linux下一样的)
(4)表高速缓存
show global status like 'open%tables%';查看打开的表的数量:
-
open_tables:是当前在缓存中打开表的数量。
-
opened_tables:是mysql自启动起,打开表的数量。
-
当Opened_tables数值非常大,说明cache太小,导致要频繁地open table,可以查看下当前的table_open_cache设置:
-
show variables like ‘table_open_cache’; 查看缓存的上限值
设置table_open_cache的值有两种方式(如果是4G左右内存的服务器,建议设为2048):
1.临时设置,重启服务后将失效
set global table_open_cache=2048;
2.修改数据库配置文件
在/etc/my.cnf 文件的[mysqld]下增减一行:
table_open_cache = 2048
(5)慢查询日志
打开慢查询日志,将那些执行时间过长且占用资源过多的SQL拿来进行EXPLAIN分析。
导致CPU过高多数是GROUP BY、ORDER BY排序问题锁导致,然后慢慢进行优化改进。比如优化INSERT语句、优化GROUP BY语句、优化ORDER BY语句、优化JOIN语句等。
查看慢查询日志开启状态
mysql> SHOW VARIABLES LIKE "%slow_query_log%";
+---------------------+-------------------------------------------------------------+
| Variable_name | Value |
+---------------------+-------------------------------------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | \MySQL\data\slow.log |
+---------------------+-------------------------------------------------------------+
2 rows in set
临时开启慢查询日志
mysql> SET GLOBAL slow_query_log = 1;
获取慢查询日志的存放路径mysql> SHOW VARIABLES LIKE "slow_query_log_file
慢查询中的SQL是由long_query_time控制的mysql> SHOW VARIABLES LIKE "long_query_time%";
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set
临时修改全局的长查询时间微秒限制
mysql> SET GLOBAL long_query_time=4;
设置日志存储方式
mysql> SHOW VARIABLES LIKE "%log_output%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | FILE |
+---------------+-------+
1 row in set
日志存储方式 | 描述 |
---|---|
FILE | 将日志存入文件 |
TABLE | 将日志存入数据库,日志信息默认写入mysql.slow_log表中。 |
临时设置日志存储方式
mysql> SET GLOBAL log_output="FILE,TABLE";
查询有多少条慢查询记录
mysql> SHOW GLOBAL STATUS LIKE "%Slow_queries%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries | 0 |
+---------------+-------+
1 row in set