第一步、检测系统状态

通过系统自带工具检测系统状态,cpu、内存、交换空间、磁盘利用率,还有关注那些占用cpu和内存的进程。


sar检测系统是否存在IO问题

yum -y install systat    

sar -u 2 10    每隔2秒执行一次,共执行10次

root@cp-mysql04-new zones]# sar -u 2 10

Linux 3.10.0-123.el7.x86_64 (cp-mysql04-new) 2016年01月07日 _x86_64_ (8 CPU)

15时03分43秒     CPU     %user     %nice   %system   %iowait    %steal     %idle

15时03分45秒     all      0.06      0.00      0.00      0.19      0.00     99.75

15时03分47秒     all      0.06      0.00      0.06      0.19      0.00     99.69


sar -u -o /tmp/sar.txt 2 20 每2秒采集一次,共20次,结果写到指定文件中

sar 命令行的常用格式:

sar [options] [-A] [-o file] t [n]

在命令行中,n 和t 两个参数组合起来定义采样间隔和次数,t为采样间隔,是必须有
的参数,n为采样次数,是可选的,默认值是1,-o file表示将命令结果以二进制格式
存放在文件中,file 在此处不是关键字,是文件名。options 为命令行选项,sar命令
的选项很多,下面只列出常用选项:

-A:所有报告的总和。
-u:CPU利用率
-v:进程、I节点、文件和锁表状态。
-d:硬盘使用报告。
-r:没有使用的内存页面和硬盘块。
-g:串口I/O的情况。
-b:缓冲区使用情况。
-a:文件读写情况。
-c:系统调用情况。
-R:进程的活动情况。
-y:终端设备活动情况。
-w:系统交换活动。


%user    指用户进程使用cpu资源百分比

%system    指系统进程占用cpu百分比

%iowait    等待io完成的百分比,这项值得关注。

%idle    指空闲cpu的百分比


%iowait的值很大,如果在35%以上,说明系统IO存在瓶颈,cpu花大量时间等待io完成,此时应该检测磁盘问题或更换。


磁盘I/O问题,做raid 10 可以提高性能。


vmstat监控内存&CPU资源

[root@kgj01 ~]# vmstat 1 5

procs -----------memory---------- ---swap-- -----io------ --system----  ----cpu-----

 r  b   swpd   free    buff  cache    si   so    bi    bo   in   cs us sy id  wa st

 0  0      0 5697204   1900 2080748    0    0     0     0    1    0  0  0 100  0  0

 0  0      0 5697204   1900 2080748    0    0     0     0  117  164  0  0 100  0  0

 0  0      0 5697328   1900 2080748    0    0     0     0  136  213  0  0 100  0  0

 0  0      0 5697328   1900 2080748    0    0     0     0   55   89  0  0 100  0  0

 0  0      0 5697328   1900 2080748    0    0     0     0   98  160  0  0 100  0  0


值得关注的信息 : 

磁盘IO: io-bo 磁盘写数据块数,block。如果磁盘写数据量大时,大文件写,10M不用担心;小文件写,2M内不用担心。

CPU:

    r    processes in the run queue队列等待的进程

    us    user time用户进程使用cpu时间

    sy    system time

    id    idle time

如果r列的数量大于系统中cpu的数量,说明有进程在等待cpu,系统处理变慢;如果这个数量是cpu的4倍,说明系统正面临cpu短缺,系统运行速度大幅降低。

如果id时间经常为0,或者sy占用时间是us占用时间的2倍,说明系统面临CPU资源短缺。解决:调节程序,更高效使用cpu;增加cpu性能或者数量。


二、检测mysql参数

max_connect_errors

默认10次,受信任帐号错误连接次数达到10次则自动堵塞,需要flush host解除。报错:

Host ’hostname’ is blocked because of many connection errors.

Unblock with ’mysqladmin flush-hosts’

show variables like '%errors%';

show status like '%errors%';

    查看设置最大错误连接次数的状态和设置参数


connect_timeout

指定mysql服务等待应答连接的最大时间,单位s,默认5秒,超过这个时间mysql向客户端返回bad handshake。内网高并发环境下,建议设置10-15s,避免bad handshake。并且关注thread_cache_size,设置为非0,具体大小视环境定。


skip-name-resolve

避免域名解析,可以大大加快用户获取连接的速度,特别是在网络较差的情况下。mysql收到用户发来的请求连接时,会根据请求包中获得的ip来反向查询请求者的主机名,然后会更具返回的主机名有一次去查询ip,如果两次获得的ip相同,则成功建立连接。在DNS不稳定或者局域网主机过多的情况下,建立一次成功的请求连接必然会消耗很多不必要的时间。但是加入mysql服务器的ip是广域网地址,最好不要设置skip-name-resolve.


slave-net-timeout=seconds

当slave从master读取binlog失败后,等待多长时间,重新与master建立连接,并获取数据。默认3600s,如果保证数据能够及时同步,该参数应设置在10s以下。

show variables like '%timeout%';

set global slave_net_timeout = 5;


master-connect-retry=seconds

当主从连接建立失败,间隔多久重试。默认60s,合理设置该参数。



连接数max_connections

如果连接数达到最大连接数,那不管剩余多少资源,用户的连接请求都会阻塞在外面。

max_connections,最大连接数,默认100,一般经验设置3000。win服务器连接数支持1500-1800,linux服务器可以支持8000个左右。

另外设置max_user_connections=0,表示不限制用户的最大连接数,其最大值可以等于max_connections

show variables like '%connections%';

show global status like 'max_used_connections';

    检查曾经使用最大的连接数,这个值在max_connections的85%左右比较合适,过高,则会系统使用连接数过少,系统负荷过高。



[root@mysql02 ~]# mysqladmin -uroot -pgameol32! status

Uptime: 233049  Threads: 2  Questions: 23076919  Slow queries: 114  Opens: 3705  Flush tables: 1  Open tables: 62  Queries per second avg: 99.021



show processlist;  或者 show full processlist;

MariaDB [(none)]> show processlist;

+--------+--------+------------------+---------+-------------+---------+---------------+----------------------+--------

| Id     | User   | Host             | db      | Command     | Time    | State         | Info                 | Progre

| 287662 | root   | localhost:41583  | finance | Query       |  665767 | Sending data  | SELECT COUNT(*) FROM `cash_beorder` INNER JOIN `cash_account` ON ( `cash_beorder`.`account_id` = `ca |    0.00


| 287663 | root   | localhost:41626  | finance | Query       |  665766 | Sending data   | SELECT COUNT(*) FROM `cash_beorder` INNER JOIN `cash_account` ON ( `cash_beorder`.`account_id` = `ca |    0.00


| 287664 | root   | localhost:41990  | finance | Query       |  665751 | Sending data   | SELECT COUNT(*) FROM `cash_beorder` INNER JOIN `cash_account` ON ( `cash_beorder`.`account_id` = `ca |    0.00


| 287665 | root    | localhost:42153  | finance | Query       |  665744 | Sending data   | SELECT COUNT(*) FROM `cash_beorder` INNER JOIN `cash_account` ON ( `cash_beorder`.`account_id` = `ca |    0.0


关注time列参数,分析用户进程占用mysql连接数时长

如果运行的SQL语句太多,运行时间太长,说明mysql效率有问题。必要时可以将相应的进程kill掉。

kill 287662;


MYSQL锁情况

MariaDB [(none)]> show status like '%lock%';

+------------------------------------------+-----------+

| Variable_name                            | Value     |

+------------------------------------------+-----------+

| Aria_pagecache_blocks_not_flushed        | 0         |

| Aria_pagecache_blocks_unused             | 15736     |

| Aria_pagecache_blocks_used               | 15736     |

| Binlog_group_commit_trigger_lock_wait    | 0         |

| Innodb_row_lock_waits                    | 0         |

| Innodb_s_lock_os_waits                   | 5927442   |

| Innodb_s_lock_spin_rounds                | 197658533 |

| Innodb_s_lock_spin_waits                 | 7649025   |

| Innodb_x_lock_os_waits                   | 17891     |

| Innodb_x_lock_spin_rounds                | 3111201   |

| Innodb_x_lock_spin_waits                 | 619667    |

| Key_blocks_not_flushed                   | 0         |

| Key_blocks_unused                        | 13358     |

| Key_blocks_used                          | 13389     |

| Key_blocks_warm                          | 31        |

| Table_locks_immediate                    | 12016516  |

| Table_locks_waited                       | 0         |

+------------------------------------------+-----------+



慢查询(slow query)日志

mysql> show variables like ‘%slow%’;

+———————+—————————————--------------------+

| Variable_name       | Value                                                  |

+———————+—————————————---------------------+

| log_slow_queries    | OFF                                                    |

| slow_launch_time    | 2                                                        |

| slow_query_log      | OFF                                                     |

| slow_query_log_file | /data0/mysql/3306/data/mysql1-slow.log |

+———————+—————————————----------------------+

开启慢查询日志

set global slow_query_log=on;


慢查询涉及的表的相关状态

1-表内记录数,尽量控制在500万条内,有索引情况下。一般建议200万条左右。

2-尽量使用表内索引。

3-表如果update,delete,insert频繁,可以考虑optimize table优化下文件存放,索引,存储空间。

4-优化表内update,insert,delete查询的锁定时间。

5-select for update如果条件字段无索引的话,会引起的是锁全表而不是行锁,请关注。

6-如果查询包括GROUP BY但你想要避免排序结果的消耗,你可以指定ORDER BY NULL禁止排序。


key_buffer_size索引缓存

key_buffer_size是对myISAM表性能影响最大的一个参数。

MariaDB [(none)]> show global status like 'key_read%';

+-------------------+----------+

| Variable_name     | Value    |

+-------------------+----------+

| Key_read_requests | 13915643 |

| Key_reads         | 129954   |

+-------------------+----------+

key_read_requests表示总共的索引请求数,key_reads表示请求在内存中没有找到,直接从硬盘读取索引,计算索引未命中缓存:

key_cache_miss_rate=key_reads/key_read_requests*100%

保持key_cache_miss_rate在0.1%以下都是很好的,如果在0.01%以下的话,key_buffer_size分配过的,适当减少。


created_tmp_tables 创建临时表

MariaDB [(none)]> show global status like 'created_tmp%';

+-------------------------+-------+

| Variable_name           | Value |

+-------------------------+-------+

| Created_tmp_disk_tables | 540   |

| Created_tmp_files       | 211   |

| Created_tmp_tables      | 2302  |

+-------------------------+-------+

3 rows in set (0.00 sec)

每次创建临时表,created_tmp_tables增加(内存&磁盘创建临时表),created_tmp_disk_tables磁盘创建的临时表,比较理想的配置:

created_tmp_disk_tables/created_tmp_tables*100%<=25%

临时表配置参数:

show variables where variable_name in ('tmp_table_size','max_heap_table_size');

+---------------------+----------+

| Variable_name       | Value    |

+---------------------+----------+

| max_heap_table_size | 16777216 |

| tmp_table_size      | 16777216 |

+---------------------+----------+

2 rows in set (0.00 sec)

只有16MB的临时表才能全部放内存,超过的就会用到硬盘临时表。


open_tables打开表数量

MariaDB [(none)]> show global status like '%open%table%';

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| Com_show_open_tables     | 0     |

| Open_table_definitions   | 64    |

| Open_tables              | 64    |

| Opened_table_definitions | 76    |

| Opened_tables            | 5402  |

| Slave_open_temp_tables   | 0     |

+--------------------------+-------+

6 rows in set (0.00 sec)

open_tables表示打开表的数量,opened_tables表示曾经打开过的表数量。如果opened_tables数量过大,说明配置table_open_cache缓存值可能太小,查询table_open_cache参数设置值:

MariaDB [(none)]> show variables like 'table%cache%';

+------------------------+-------+

| Variable_name          | Value |

+------------------------+-------+

| table_definition_cache | 400   |

| table_open_cache       | 64    |

+------------------------+-------+

2 rows in set (0.00 sec)

比较合适的值:

85% <= open_tables / opened_tables <= 95%



thread_cache_size  线程缓存

MariaDB [(none)]> show global status like 'thread%';

+-------------------------+----------+

| Variable_name           | Value    |

+-------------------------+----------+

| Threadpool_idle_threads | 0        |

| Threadpool_threads      | 0        |

| Threads_cached          | 0        |

| Threads_connected       | 48       |

| Threads_created         | 15023416 |

| Threads_running         | 6        |

+-------------------------+----------+

6 rows in set (0.00 sec)

如果配置thread_cache_size后,当客户端端口连接后,服务器处理客户的线程将会缓存到thread_cache中,以响应下一个客户,而不是销毁(前提缓存数未达到thread_cache_size上线)。threads_created表示曾经创建的线程数,如果发现threads_created值过大,表明mysql服务器一直在创建线程,这个比较耗资源,可以适当增加thread_cache_size值

MariaDB [(none)]> show variables like 'thread_cache_size';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| thread_cache_size | 0     |

+-------------------+-------+

1 row in set (0.00 sec



query cache 查询缓存

MariaDB [(none)]> show global status like 'qcache%';

+-------------------------+-------+

| Variable_name           | Value |

+-------------------------+-------+

| Qcache_free_blocks      | 0     |

| Qcache_free_memory      | 0     |

| Qcache_hits             | 0     |

| Qcache_inserts          | 0     |

| Qcache_lowmem_prunes    | 0     |

| Qcache_not_cached       | 0     |

| Qcache_queries_in_cache | 0     |

| Qcache_total_blocks     | 0     |

+-------------------------+-------+

8 rows in set (0.00 sec)


Qcache_free_blocks表示缓存中相邻内存块的个数,数目越大可能有碎片,flush query cache会对缓存中的碎片进行整理。

Qcache_free_memory  表示缓存中空闲内存

 Qcache_hits命中查询缓存的次数

Qcache_inserts插入一个查询到缓存的次数,命中次数除以插入次数就是不中比率。

Qcache_lowmem_prunes:缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看;如果这个数字在不断增长,就表示可能碎片非常严重,或者内存很少。(上面的 free_blocks和free_memory可以告诉您属于哪种情况)

Qcache_not_cached:不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句或者用了now()之类的函数。

Qcache_queries_in_cache:当前缓存的查询(和响应)的数量。

Qcache_total_blocks:缓存中块的数量。


MariaDB [(none)]> show variables like 'query_cache%';

+------------------------------+---------+

| Variable_name                | Value   |

+------------------------------+---------+

| query_cache_limit            | 1048576 |

| query_cache_min_res_unit     | 4096    |

| query_cache_size             | 0       |

| query_cache_strip_comments   | OFF     |

| query_cache_type             | ON      |

| query_cache_wlock_invalidate | OFF     |

+------------------------------+---------+

6 rows in set (0.00 sec)

各字段的解释:

query_cache_limit:超过此大小的查询将不缓存

query_cache_min_res_unit:缓存块的最小大小

query_cache_size:查询缓存大小

query_cache_type:缓存类型,决定缓存什么样的查询,示例中表示不缓存 select sql_no_cache 查询

query_cache_wlock_invalidate:当有其他客户端正在对MyISAM表进行写操作时,如果查询在query cache中,是否返回cache结果还是等写操作完成再读表获取结果。

query_cache_min_res_unit的配置是一柄”双刃剑”,默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小数据查询,就容易造成内存碎片和浪费。

查询缓存碎片率 = Qcache_free_blocks / Qcache_total_blocks * 100%

如果查询缓存碎片率超过20%,可以用FLUSH QUERY CACHE整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话。

查询缓存利用率 = (query_cache_size – Qcache_free_memory) / query_cache_size * 100%

查询缓存利用率在25%以下的话说明query_cache_size设置的过大,可适当减小;查询缓存利用率在80%以上而且Qcache_lowmem_prunes > 50的话说明query_cache_size可能有点小,要不就是碎片太多。

查询缓存命中率 = (Qcache_hits – Qcache_inserts) / Qcache_hits * 100%

示例服务器 查询缓存碎片率 = 20.46%,查询缓存利用率 = 62.26%,查询缓存命中率 = 1.94%,命中率很差,可能写操作比较频繁吧,而且可能有些碎片。