mysql系统视图的使用

Sys schema视图摘要

  1. 主机相关:以host_summary开头,主要汇总了IO延迟的信息。
  2. Innodb相关:以innodb开头,汇总了innodb buffer信息和事务等待innodb锁的信息。
  3. I/o相关:以io开头,汇总了等待I/O、I/O使用量情况。
  4. 内存使用情况:以memory开头,从主机、线程、事件等角度展示内存的使用情况
  5. 连接与会话信息:processlist和session相关视图,总结了会话相关信息。
  6. 表相关:以schema_table开头的视图,展示了表的统计信息。
  7. 索引信息:统计了索引的使用情况,包含冗余索引和未使用的索引情况。
  8. 语句相关:以statement开头,包含执行全表扫描、使用临时表、排序等的语句信息。
  9. 用户相关:以user开头的视图,统计了用户使用的文件I/O、执行语句统计信息。
  10. 等待事件相关信息:以wait开头,展示等待事件的延迟情况。
#1. 查询冗余索引
select * from sys.schema_redundant_indexes;
#2. 查询未使用过的索引
select * from sys.schema_unused_indexes;
#3. 查询索引的使用情况
select index_name,rows_selected,rows_inserted,rows_updated,rows_deleted
from sys.schema_index_statistics where table_schema='dbname' 

# 1. 查询表的访问量
select table_schema,table_name,sum(io_read_requests+io_write_requests) as io from
sys.schema_table_statistics group by table_schema,table_name order by io desc;
# 2. 查询占用bufferpool较多的表
select object_schema,object_name,allocated,data
from sys.innodb_buffer_stats_by_table order by allocated limit 10;
# 3. 查看表的全表扫描情况
select * from sys.statements_with_full_table_scans where db='dbname';

#1. 监控SQL执行的频率
select db,exec_count,query from sys.statement_analysis
order by exec_count desc;
#2. 监控使用了排序的SQL
select db,exec_count,first_seen,last_seen,query
from sys.statements_with_sorting limit 1;
#3. 监控使用了临时表或者磁盘临时表的SQL
select db,exec_count,tmp_tables,tmp_disk_tables,query
from sys.statement_analysis where tmp_tables>0 or tmp_disk_tables >0
order by (tmp_tables+tmp_disk_tables) desc;

#1. 查看消耗磁盘IO的文件
select file,avg_read,avg_write,avg_read+avg_write as avg_io
from sys.io_global_by_file_by_bytes order by avg_read  limit 10

#1. 行锁阻塞情况
select * from sys.innodb_lock_waits

锁相关

innodb_trx
存储了当前正在执行的事务信息
trx_id:事务ID。
trx_state:事务状态,有以下几种状态:RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING。
trx_started:事务开始时间。
trx_requested_lock_id:事务当前正在等待锁的标识,可以和 INNODB_LOCKS 表 JOIN 以得到更多详细信息。
trx_wait_started:事务开始等待的时间。
trx_mysql_thread_id:事务线程 ID,可以和 PROCESSLIST 表 JOIN。
trx_tables_locked:表示该事务目前加了多少个表级锁。
trx_lock_structs:表示该事务生成了多少个内存中的锁结构。
trx_lock_memory_bytes:事务锁住的内存大小,单位为 BYTES。
trx_rows_locked:表示该事务目前加了多少个行级锁。

innodb_locks
记录了锁信息
如果一个事务想要获取到某个锁但未获取到,则记录该锁信息
如果一个事务获取到了某个锁,但是这个锁阻塞了别的事务,则记录该锁信息
但是无法通过该表查询到谁被阻塞,谁持有未释放。
lock_id:锁 ID。
lock_trx_id:拥有锁的事务 ID。可以和 INNODB_TRX 表 JOIN 得到事务的详细信息。
lock_mode:锁的模式。
lock_type:锁的类型。RECORD 代表行级锁,TABLE 代表表级锁。
lock_table:被锁定的或者包含锁定记录的表的名称。

innodb_lock_waits
表明每个阻塞的事务是因为获取不到哪个事务持有的锁而被阻塞
requesting_trx_id:–获取不到锁而被阻塞的事务id(等待方)
requested_lock_id:-- 请求锁ID ,事务所等待的锁定的 ID。可以和 INNODB_LOCKS 表 JOIN。
blocking_trx_id: --获取到别的事务需要的锁而阻塞其事务的事务id(当前持有方,待释放)
blocking_lock_id: --这一事务的锁的 ID,该事务阻塞了另一事务的运行。可以和 INNODB_LOCKS 表 JOIN。

processlist
id:标识ID。这与在SHOW PROCESSLIST语句的Id列、Performance Schema threads表的PROCESSLIST_ID列中显示的值类型相同,并由CONNECTION_ID()函数返回
user:发出该语句的mysql用户。
host:发出该语句的客户机的主机名(系统用户除外,没有主机)。
db:默认数据库。
command:线程正在执行的命令的类型。
time:线程处于当前状态的时间(以秒为单位)。
state:指示线程正在执行的操作、事件或状态。
info:线程正在执行的语句,如果没有执行任何语句,则为NULL。

如何借助这几张表来定位到有行锁等待?
查看当前有无锁等待:

show status like 'innodb_row_lock%';

查看哪个事务在等待(被阻塞了):

select * from information_schema.INNODB_TRX WHERE trx_state='LOCK WAIT'\G

trx_state :表示该事务处于锁等待状态。
trx_query : 当前被阻塞的SQL。
trx_mysql_thread_id: 线程ID。
trx_id:事务ID。

查询该事务被哪个事务给阻塞了:
从innodb_trx获取到被阻塞的trx_id,及阻塞该事务的trx_id,本例处为3933
根据trx_id,仍从innodb_trx表可查询到trx_mysql_thread_id,本例处为970

select * from innodb_lock_waits;
select * from information_schema.innodb_trx where trx_id=3933 \G
SELECT * FROM performance_schema.threads WHERE processlist_id=970\G

根据线程id,查询表拿到thread_id,本例处为为995

SELECT * FROM performance_schema.threads WHERE processlist_id=970\G

根据thread_id,查询当前锁源的sql

SELECT * FROM performance_schema.events_statements_current WHERE thread_id=995\G

整个流程如下:
(1)首先查询是否有锁,根据锁查到被锁的trx_id
(2)根据被锁的trx_id可以查到锁源的trx_id
(3)根据锁源的trx_id查到trx_mysql_thread_id
(4)再根据trx_mysql_thread_id查到thread_id
(5)最后,用thread_id查找到锁源的sql

sys.innodb_lock_waits
locked_table : 哪张表出现的等待
waiting_trx_id: 等待的事务(与上个视图trx_id 对应)
waiting_pid : 等待的线程号(与上个视图trx_mysql_thread_id)
blocking_trx_id : 锁源的事务ID
blocking_pid : 锁源的线程号

 select * from sys.innodb_lock_waits\G

获取到锁源的blocking_pid,本例中为976(=processlist表的id),根据此id找到thread_id,再根据thread_id找到对应的sql

两种找到锁源SQL步骤是一样的

锁源的事务trx_id -->pnformaction_schema.processlist表的线程id–>performance_schema.threads表的thread_id–>performance_schema.events_statements_current 或performance_schema.events_statements_history查看sql

注:下面所指的id含义相同
information_schema.innodb_trx(trx_mysql_thread_id)
information_schema.processlist(id)
sys.innodb_lock_waits(waiting_pid,blocking_pid)

sys.sys.innodb_lock_waits的应用
查看锁等待相关的(阻塞线程、被阻塞线程信息及相关用户、IP、PORT、locked_type锁类型

SELECT locked_table,
       locked_index,
       locked_type,
       blocking_pid,
       concat(T2.USER,'@',T2.HOST) AS "blocking(user@ip:port)",
       blocking_lock_mode,
       blocking_trx_rows_modified,
       waiting_pid,
       concat(T3.USER,'@',T3.HOST) AS "waiting(user@ip:port)",
       waiting_lock_mode,
       waiting_trx_rows_modified,
       wait_age_secs,
       waiting_query
FROM sys.x$innodb_lock_waits T1
LEFT JOIN INFORMATION_SCHEMA.processlist T2 ON T1.blocking_pid=T2.ID
LEFT JOIN INFORMATION_SCHEMA.processlist T3 ON T3.ID=T1.waiting_pid;

等待的持续时间(单位秒>20s)

SELECT trx_mysql_thread_id AS PROCESSLIST_ID,
       NOW(),
       TRX_STARTED,
       TO_SECONDS(now())-TO_SECONDS(trx_started) AS TRX_LAST_TIME ,
       USER,
       HOST,
       DB,
       TRX_QUERY
FROM INFORMATION_SCHEMA.INNODB_TRX trx
JOIN sys.innodb_lock_waits lw ON trx.trx_mysql_thread_id=lw.waiting_pid
JOIN INFORMATION_SCHEMA.processlist pcl ON trx.trx_mysql_thread_id=pcl.id
WHERE trx_mysql_thread_id != connection_id()
  AND TO_SECONDS(now())-TO_SECONDS(trx_started) >= 20 ;

参考:https://blog.51cto.com/u_13874232/5151194

你可能感兴趣的:(mysql系统视图的使用)