上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
9.1 查看慢SQL语句慢在哪里
如果我们频繁地在慢查询日志中发现某个语句执行缓慢,且在表结构、索引结构、统计信息中都无法找出原因时,则可以利用sys系统库中的撒手锏:sys.session视图结合performance_schema的等待事件来找出症结所在。那么session视图有什么用呢?使用它可以查看当前用户会话的进程列表信息,数据来源于sys.processlist视图(使用该视图可以查询所有前台和后台线程的状态信息,默认按照进程等待时间和最近一条语句执行完成的时间降序排列。数据来源:performance_schema的threads、events_waits_current、events_statements_current、events_stages_current、events_transactions_current、session_connect_attrs等表和sys.x$memory_by_thread_by_current_bytes视图),查询结果字段与processlist视图类似,但session视图过滤掉了后台线程,只显示与前台(用户)线程相关的统计数据。该视图在MySQL 5.7.9中是新增的。
下面是使用session视图查询的结果集。
# 首先需要启用与等待事件相关的instruments和consumers,否则last_wait字段值可能为NULL mysql> call sys.ps_setup_enable_instrument('wait'); +-------------------------+ | summary | +-------------------------+ | Enabled 315 instruments | +-------------------------+ 1 row in set(0.02 sec) Query OK, 0 rows affected(0.02 sec) mysql> call sys.ps_setup_enable_consumer('wait'); +---------------------+ | summary | +---------------------+ | Enabled 3 consumers | +---------------------+ 1 row in set(0.00 sec) Query OK, 0 rows affected(0.00 sec) # 然后,使用session视图进行查询(这里只查询command为query的线程信息,代表正在执行查询) mysql> select * from session where command='query' and conn_id! =connection_id()\G *************************** 1. row *************************** thd_id: 48 # 内部线程ID conn_id: 6 # 连接ID,即processlist_id user:admin@localhost # 对于前台线程,该字段值为account名称;对于后台线程,该字段值为后台线程名称 db: xiaoboluo # 线程的默认数据库,如果没有默认数据库,则该字段值为NULL command: Query # 对于前台线程,表示线程正在执行的客户端代码对应的命令类型,如果会话处于空闲状态,则该字段值为’Sleep';对于后台超线程,该字段值为NULL state: Sending data# 表示线程正在做什么:什么事件或状态,与processlist表中的state字段值一样 time: 72 # 表示线程处于当前状态已经持续了多长时间(秒) current_statement: select * from test limit 1 for update # 线程当前正在执行的语句,如果没有执行任何语句,该字段值为NULL statement_latency: 1.20 m # 线程当前语句已经执行了多长时间。该字段是MySQL 5.7.9中新增的 progress: NULL # 在支持进度报告的阶段事件中统计的工作进度百分比。该字段是MySQL 5.7.9中新增的 lock_latency: 169.00 us # 当前语句的锁等待时间 rows_examined: 0 # 当前语句从存储引擎读取的数据行数 rows_sent: 0 # 当前语句返回给客户端的数据行数 rows_affected: 0 # 受当前语句影响的数据行数(DML语句对数据执行变更才会影响行) tmp_tables: 0 # 当前语句创建的内部内存临时表的数量 tmp_disk_tables: 0 # 当前语句创建的内部磁盘临时表的数量 full_scan: NO # 当前语句执行的全表扫描次数 last_statement: NULL # 如果在 threads 表中没有找到正在执行的语句或正在等待执行的语句,那么在该字段可以显示线程执行的最后一条语句(在 events_statements_current 表中查找,该表会为每一个线程保留最后一条语句执行的事件信息,其他有current后缀的事件记录表也类似) last_statement_latency: NULL # 线程执行的最后一条语句执行了多长时间 current_memory: 461 bytes # 当前线程分配的字节数 last_wait: wait/io/table/sql/handler # 线程最近的等待事件的等待时间(执行时间),从这里可以看到,当前正在等待表级别的I/O last_wait_latency: Still Waiting # 线程最近的等待事件的等待时间(执行时间) source: handler.cc:3185 # 线程最近的等待事件检测代码的源文件和行号 trx_latency: NULL # 线程当前正在执行的事务已经执行了多长时间。该字段是MySQL 5.7.9中新增的 trx_state: NULL # 线程当前正在执行的事务的状态。该字段是 MySQL 5.7.9中新增的 trx_autocommit: NULL # 线程当前正在执行的事务的提交模式,有效值为:'ACTIVE'、'COMMITTED'、'ROLLED BACK'。该字段是MySQL 5.7.9中新增的 pid: 3788 # 客户端进程ID。该字段是MySQL 5.7.9中新增的 program_name: mysql # 客户端程序名称。该字段是MySQL 5.7.9中新增的 1 row in set(0.15 sec)