连接相关
threads_connected:当前打开的连接数
1
2
3
4
5
6
7
|
select round((P1.variable_value)/(P2.variable_value), 4) as connections,
P1.variable_value as threads_connected,
P2.variable_value as max_connections
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_VARIABLES P2
WHERE P1.variable_name = 'threads_connected'
AND P2.variable_name = 'max_connections';
|
连接数/最大连接数比值较大,则需要调整max_connections或检查业务是否使用正常
max_used_connections:最大同时使用的连接数
1
2
3
4
5
6
7
|
select round((P1.variable_value)/(P2.variable_value), 4) as connections_ever_seen,
P1.variable_value as max_used_connections,
P2.variable_value as max_connections
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_VARIABLES P2
WHERE P1.variable_name = 'max_used_connections'
AND P2.variable_name = 'max_connections';
|
如果这个值大于0.8,则mysql server出现过too many connections的错误,可以查询max_used_connections_time来获取最大连接数出现的时间
1
|
show status like '%max_used_connections_time%';
|
Connections: 尝试连接到mysql的连接数量(成功或失败)
Threads_created: 用来处理连接的线程数量,如果Threads_created较大,则可能需要修改thread_cache_size。cache miss rate 计算方式为Threads_created/Connections
1
2
3
4
5
|
select round((P2.variable_value / P1.variable_value), 4), P2.variable_value, P1.variable_value
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2
WHERE P1.variable_name = 'Connections'
AND P2.variable_name = 'Threads_created';
|
查询相关
handler_read_rnd_next:读表中下一行数据的请求的次数,如果这个值很高则说明很可能客户端在进行大量的表扫描,很有可能没有有效利用索引进行查询;
handler_read_rnd:读取表中固定一行的请求次数,这个数值高说明很多查询需要对result进行排序,也有全表扫描的可能性;
handler_read_first:读取全部索引的请求次数,如果这个值很高则说明mysql server正在进行低效的全索引扫描,例如select id from ids,其中id为索引
handler_read_next:通过索引读取下一行的请求数量,如果这个值很高则说明在对索引进行范围查询
handler_read_key:通过索引读取一行数据的请求数量,这个值越高说明索引越高效
handler_read_prev:读取索引前一行数据的请求数量,这个值越高说明使用order by * desc的次数越多
则整个server进行全表扫描的比例可以通过
$ full_scan_rate = \frac{(handler_read_rnd_next + handler_read_rnd)}{(handler_read_rnd_next + handler_read_rnd + handler_read_first + handler_read_next + handler_read_key + handler_read_prev)} $
(handler_read_rnd_next + handler_read_rnd) / (handler_read_rnd_next + handler_read_rnd + handler_read_first + handler_read_next + handler_read_key + handler_read_prev)
来计算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
select round((P2.variable_value + P1.variable_value) /
(P2.variable_value + P1.variable_value + P3.variable_value + P4.variable_value + P5.variable_value +
P6.variable_value), 4) as full_table_scan_rate,
P1.variable_value as Handler_read_rnd_next,
P2.variable_value as Handler_read_rnd,
P3.variable_value as Handler_read_first,
P4.variable_value as Handler_read_next,
P5.variable_value as Handler_read_key,
P6.variable_value as Handler_read_prev
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2,
performance_schema.GLOBAL_STATUS P3,
performance_schema.GLOBAL_STATUS P4,
performance_schema.GLOBAL_STATUS P5,
performance_schema.GLOBAL_STATUS P6
WHERE P1.variable_name = 'Handler_read_rnd_next'
AND P2.variable_name = 'Handler_read_rnd'
AND P3.variable_name = 'Handler_read_first'
AND P4.variable_name = 'Handler_read_next'
AND P5.variable_name = 'Handler_read_key'
AND P6.variable_name = 'Handler_read_prev';
|
如果这个值大于25%则需要开启慢查询日志看下查询效率
select_full_join:没有使用index进行join的数量,大于0需要特别注意
1
2
3
|
select *
from performance_schema.GLOBAL_STATUS
where variable_name = 'select_full_join';
|
sort_merge_passes:使用排序的时候需要merge的part的数量,如果较大,可能需要调整sort_buffer_size和read_rnd_buffer_size
1
2
3
|
select *
from performance_schema.GLOBAL_STATUS
where variable_name = 'sort_merge_passes';
|
sort_scan: 通过扫描表完成排序的数量
sort_range: The number of sorts that were done using ranges.
通过sort_merge_passes / (sort_scan + sort_range)来衡量排序的效率
1
2
3
4
5
6
7
8
9
10
|
select round((P1.variable_value) / (P2.variable_value + P3.variable_value), 4) as sort_passes,
P1.variable_value as sort_merge_passes,
P2.variable_value as sort_scan,
P3.variable_value as sort_range
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2,
performance_schema.GLOBAL_STATUS P3
WHERE P1.variable_name = 'sort_merge_passes'
AND P2.variable_name = 'sort_scan'
AND P3.variable_name = 'sort_range';
|
innodb_buffer_pool
innodb_buffer_pool_read_requests: 读请求数
innodb_buffer_pool_reads: 需要直接从磁盘中读的请求的数量
innodb_buffer_pool命中率:
1
2
3
4
5
6
7
8
9
10
|
select round((1 - P2.variable_value / P1.variable_value), 4), P2.variable_value, P1.variable_value
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2
WHERE P1.variable_name = 'innodb_buffer_pool_read_requests'
AND P2.variable_name = 'innodb_buffer_pool_reads';
select pool_id,hit_rate,pages_made_young,pages_not_made_young from information_schema.innodb_buffer_pool_stats\G;
# 查询lru的状态
select table_name,space,page_number,page_type from information_schema.innodb_buffer_page_lru where space=1;
select table_name,space,page_number,page_type from information_schema.innodb_buffer_page_lru where oldest_modification>0;
|
innodb_buffer_pool_pages_dirty: buffer pool中脏页(dirty page:在内存中更新但是没有还没有写到datafile中的页;clean page:内存中的数据和data file中的数据一致的页)的数量
innodb_buffer_pool_pages_total: buffer pool中页的总数
衡量innodb flush的速率,如果是读少写多的库,则对应的rate会变大
1
2
3
4
5
6
7
|
select round((P1.variable_value)/(P2.variable_value), 4) as dirty_page,
P1.variable_value as innodb_buffer_pool_pages_dirty,
P2.variable_value as innodb_buffer_pool_pages_total
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2
WHERE P1.variable_name = 'innodb_buffer_pool_pages_dirty'
AND P2.variable_name = 'innodb_buffer_pool_pages_total';
|
如果dirty_page的比例大于75%且持续时间很长,则可能需要调整innodb_buffer_pool_size或者换一个好一点的磁盘
innodb_buffer_pool_wait_free:通常情况下,innodb写buffer pool发生是后台线程完成的,但是如果innodb需要读或者创建页的时候没有clean page可用,则innodb需要先将也写dirty page刷新到data file中并等待刷新操作完成,innodb_buffer_pool_wait_free这个表明正在等待flush操作的线程数,如果innodb_buffer_pool_size设置得当,则这个数值会很低;
innodb_buffer_pool_write_requests:Innodb写完成的数量
衡量innodb等待刷新脏页数据的比例:
1
2
3
4
5
6
|
select round((P1.variable_value)/(P2.variable_value), 4) as dirty_page,
P1.variable_value as innodb_buffer_pool_wait_free,
P2.variable_value as innodb_buffer_pool_write_requests
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2
WHERE P1.variable_name = 'innodb_buffer_pool_wait_free' AND P2.variable_name = 'innodb_buffer_pool_write_requests';
|
这个数据太大则表明innodb_buffer_pool_size太小。小于1一般是正常数据
innodb_log_waits:log buffer(缓存需要写redo log的内存区域)需要等待flush操作的次数
innodb_log_writes:写redo log的次数
Innodb等待redolog写入的概率:
1
2
3
4
5
6
|
select round((P1.variable_value)/(P2.variable_value), 4) as redolog_wait,
P1.variable_value as innodb_log_waits,
P2.variable_value as innodb_log_writes
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2
WHERE P1.variable_name = 'innodb_log_waits' AND P2.variable_name = 'innodb_log_writes';
|
如果这个数值大于1,则需要调整innodb_log_buffer_size
opened_tables:table open number
table_cache_usage=opened_tables/table_open_cache
1
2
3
4
5
6
|
select round((P1.variable_value)/(P2.variable_value), 4) as table_cache_usage,
P1.variable_value as opened_tables,
P2.variable_value as table_open_cache
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_VARIABLES P2
WHERE P1.variable_name = 'opened_tables' AND P2.variable_name = 'table_open_cache';
|
小于1需要调整table_open_cache
Created_tmp_disk_tables:mysql server在磁盘上创建临时表的sql数量
Created_tmp_files:mysqld创建的tmp文件的数量
Created_tmp_tables:执行sql的时候创建临时表的数量
mysql server创建临时文件的概率
1
2
3
4
5
6
|
select round((P1.variable_value)/(P2.variable_value), 4) as tmp_table_disk_usage,
P1.variable_value as Created_tmp_disk_tables,
P2.variable_value as Created_tmp_tables
from performance_schema.GLOBAL_STATUS P1,
performance_schema.GLOBAL_STATUS P2
WHERE P1.variable_name = 'Created_tmp_disk_tables' AND P2.variable_name = 'Created_tmp_tables';
|
一些SQL
- 查看非sleep的线程
1
|
SELECT * FROM information_schema.processlist WHERE command <> 'sleep';
|