这是《高性能 MySQL(第三版)》第三章的读书笔记。

关于服务,常见的问题有:

  • 如何确认服务器是否发挥了最大性能
  • 找出执行慢的语句,为何执行慢
  • 为何在用户端发生间歇性的停顿、卡死

通过性能剖析(profiling)分析服务器的性能并找出花费时间最多的地方,有助于解决上述问题。

1. 性能优化简介

性能通常可以认为就是响应时间(Latency,延迟),而性能优化就是减少响应时间。

要想优化性能,首先需要知道性能的瓶颈在哪里。这就需要用到测试了。

2. 性能测试

2.1 对应用程序进行性能测试

每种语言都有专门的测试程序,对于 PHP,可以使用的有:

  • xhprof:轻量小巧,可在生成环境部署。参考 这里
  • xdebug:检测范围大,开销大,适合测试环境。

2.2 对数据库进行性能测试

2.2.1 分析服务器负载

通过分析服务器负载,定位需要优化的单条查询。

捕获 MySQL 的查询到日志文件

MySQL 中,慢查询日志是开销最低、精度最高的测量查询时间的工具。运行时间超过 long_query_time 值语句会被记录到慢查询日志中。long_query_time 单位是秒,默认值为 10,可以设置为 0 来捕获所有的查询。慢查询日志需要手动开启,开启后会略微影响性能。慢查询日志可以写入文件或数据库,但写入到数据库时会影响性能且时间粒度退化为秒级。

MySQL 中还有另外一种查询日志,叫通用日志,但可用信息太少且资源消耗大,基本不用。

慢查询日志相关参数如下,使用可以参考 这里

  • slow_query_log:是否开启慢查询日志,1 开启,0 关闭。
  • log-slow-queries:旧版(5.6以下版本)MySQL数据库慢查询日志存储路径。默认给一个缺省的文件 host_name-slow.log
  • slow-query-log-file:新版(5.6及以上版本)MySQL数据库慢查询日志存储路径。默认给一个缺省的文件 host_name-slow.log
  • long_query_time :慢查询阈值,当查询时间多于设定的阈值时,记录日志。
  • log_queries_not_using_indexes:未使用索引的查询也被记录到慢查询日志中(可选项)。
  • log_output:日志存储方式。log_output=’FILE’表示将日志存入文件,默认值是’FILE’。log_output=’TABLE’表示将日志存入数据库,这样日志信息就会被写入到 mysql.slow_log 表中。MySQL 数据库支持同时两种日志存储方式,配置的时候以逗号隔开即可,如:log_output=’FILE,TABLE’。日志记录到系统的专用日志表中比记录到文件耗费更多的系统资源,因此对于需要启用慢查询日志,又需要能够获得更高的系统性能,建议优先记录到文件。

分析查询日志

分析慢查询日志可以使用 MySQL 自带的 mysqldumpslow 工具。要用慢查询日志生成分析报告可以使用 pt-query-digest 工具。

2.2.2 分析单条查询

定位到需要优化的单条查询后,开始优化。

SHOW PROFILE(以被 performance_schema 替代)

都废弃了,别研究了。

–使用前先通过 have_profiling 参数查看当前 MySQL是否支持 profile:–

mysql> select @@have_profiling;
+------------------+
| @@have_profiling |
+------------------+
| YES |
+------------------+
1 row in set, 1 warning (0.01 sec) mysql> show warnings;
+---------+------+---------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1287 | '@@have_profiling' is deprecated and will be removed in a future release. |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

–默认禁用,可以通过服务器变量在会话级别启用:–

mysql> SET profiling = 1;

Performace Schema

参考这里

Performace Schema 是目前 MySQL(5.7 及以上版本)主推的性能测试工具,默认开启。首次安装 MySQL 后,你会发现其默认安装了几个数据库,其中的 performace_schema 就是用于配置 Performace Schema 的。

SHOW STATUS

SHOW STATUS 命令返回一些服务器级别的全局计数器或某个会话级别的计数器。可以显示活动频繁程度,但是无法给出消耗的时间。

mysql> show global status;
+-----------------------------------------------+--------------------------------------------------+
| Variable_name | Value |
+-----------------------------------------------+--------------------------------------------------+
| Aborted_clients | 275 |
| Aborted_connects | 80872 |
| Binlog_cache_disk_use | 0 |
...
| Threads_running | 1 |
| Uptime | 6661773 |
| Uptime_since_flush_status | 6661773 |
| validate_password_dictionary_file_last_parsed | 2018-01-31 15:35:09 |
| validate_password_dictionary_file_words_count | 0 |
+-----------------------------------------------+--------------------------------------------------+
355 rows in set (0.03 sec)

2.3 诊断间歇问题

应用偶尔停顿、数据库间歇性的慢查询的可能原因有:

  • 应用通过接口从运行很慢的外部服务获取数据
  • memcached 中的重要缓存条目过期,导致大量请求落到 MySQL 以重新生成缓存条目
  • DNS 查询偶尔超时
  • 互斥锁争用或内部删除查询缓存的算法效率太低,MySQL 的查询缓存导致服务短暂停顿
  • 并发度超过阈值时,InnoDB 的扩展性限制导致查询计划的优化需要很长时间

解决间歇性问题有常见的套路和工具,定位好问题才能进行之后的操作。

2.3.1 单条查询问题还是服务器问题

SHOW GLOBAL STATUS

SHOW STATUS 或 SHOW SESSION STATUS 显示当前会话级别的信息,SHOW GLOBAL STATUS 显示服务器级别的信息。完整差异可以参考 SHOW GLOBAL STATUS vs SHOW STATUS

以较高的频率执行 SHOW GLOBAL STATUS 命令捕获数据,问题出现时可以通过某些计数器(Threads_running、Threads_connected、Questions、Queries)的“尖刺”和“凹陷”来发现问题。SHOW GLOBAL STATUS 命令的用法简单且执行时不需要特殊权限(登录数据库的用户都可以使用)、对服务器影响小。

下面示例通过 -i1 选项每秒捕捉一次数据,输出给 awk 计算并输出每秒的查询数、Threads_connected、Threads_running:

[root@VM_120_242_centos ~]# mysqladmin -uroot -p ext -i1 | awk '/Queries/{q=$4-qp;qp=$4} /Threads_connected/{tc=$4} /Threads_running/{printf "%d %d %d\n", q, tc, $4}'
Enter password:
1554866 1 1
1 1 1
1 1 1

下面示例通过 -i1 选项每秒捕捉一次数据,通过 -r 选项展示差值,输出给 awk 计算并输出每秒的查询数:

# mysqladmin -uroot -p ext -i1 -r | awk '/Queries/{q=$4} /Threads_connected/{tc=$4} /Threads_running/{printf "%d %d %d\n", q, tc, $4}'
Enter password:
1554856 1 1
1 0 0
1 0 0
1 0 0

SHOW PROCESSLIST

不停的捕获 SHOW PROCESSLIST 的输出,可以观察是否有大量线程处于不正常状态或有不正常特征。例如查询很少会长时间处于“statictics”状态。

示例,通过命令尾部使用 \G 替换分号可以垂直输出结果,通过 sort|uniq|sort 命令可以计算某个列值出现的次数:

[root@VM_120_242_centos ~]# mysql -uroot -p -e 'SHOW PROCESSLIST\G' | grep State: | sort | uniq -c | sort -rn
Enter password:
2 State:
1 State: starting

除了通过命令行外,也可以直接查询 INFORMATION_SCHEMA 数据库中的 PROCESSLIST 表。

使用查询日志

需要开启慢查询日志,并在全局级别设置 long_query_time 为 0,然后重置所有连接以使新的全局设置生效。

好的工具可以帮助诊断问题,否则就要去几百 GB 的日志文件中查找问题。下面示例的一行代码可以根据 MySQL 每秒将当前时间写入日志中的模式统计每秒的查询数量:

awk '/^# Time:/{print $3, $4, c; c=0}/^# User/{c++}' slow-query.log

理解发现的问题

建议刚开始诊断问题时,先使用 SHOW STATUS 和 SHOW PROCESSLIST。这两种方法开销低,且可以通过 shell 或反复查询来收集数据。分析慢查询日志则比较困难。

2.3.2 捕获诊断数据

诊断间歇性问题,需要收集尽可能多的数据。需要两个工具:

  • 触发器,即区分问题的方法
  • 收集诊断数据的工具

诊断触发器

触发器需要避免“误报”和“漏检”。

通常将触发器阈值调整为正常情况的一倍左右。比如 Threads_running 在正常情况下是 10,则触发器的阈值可以设置为 20。对于 Threads_connected 如果正常值为 150,则阈值可以是 300。

另外,还需要设置持续时间。比如 Threads_running 连续 3 秒钟超过 20,则认为是异常情况。可以使用“pt-stalk”工具。

需要收集的数据类型

确定诊断触发器后,可以开启进程收集数据。数据应该尽可能多,包括系统状态、CPU 利用率、磁盘使用率和可用空间、内存利用率、ps 命令的输出采样,以及从 MySQL 获得的信息,包括 SHOW STATUS、SHOW INNODB STATUS、SHOW PROCESSLIST。

Linux 上可用的服务器内部诊断工具有 oprofile、strace(生产环境中使用有风险)。要剖析查询可用 tcpdump。

可以通过 GDB 堆栈跟踪分析等待原因。跟踪时先启动 GDB,然后附加(attach)到 mysqld 进程,将所有线程的堆栈都存储起来。然后利用脚本汇总类似的堆栈信息,再利用 sort|uniq|sort 排序。

解释结果数据

2.3.3 案例

2.4 其他分析工具

2.4.1 USER_STATISTICS 表

INFORMATION_SCHEMA 库中的表,存储了各个数据库的信息及所有活动的统计信息,可以得知哪个数据库的哪个表、哪个索引使用的最频繁。

表索引的信息。SHOW INDEX FROM schemaname.tablename; 命令从这个表获取结果。

mysql> SHOW INDEX FROM szhuizhong.users;
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| users | 0 | PRIMARY | 1 | UserID | A | 1460 | NULL | NULL | | BTREE | | |
| users | 0 | Account_index | 1 | Account | A | 1460 | NULL | NULL | | BTREE | | |
| users | 1 | CorpID | 1 | FromID | A | 2 | NULL | NULL | YES | BTREE | | |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

5. 总结

要解决问题,首先要搞清楚问题。所有的查询记录都要记录到日志中,然后用 pt-query-digest 工具生成系统级别的剖析报告。

MySQL 服务器性能剖析的更多相关文章

  1. 提升mysql服务器性能(复制原理与拓扑优化)

    原文:提升mysql服务器性能(复制原理与拓扑优化) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/details/9008171 ...

  2. 提升mysql服务器性能(HA MMM MHA MaxScale)

    原文:提升mysql服务器性能(HA MMM MHA MaxScale) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/detai ...

  3. 提升mysql服务器性能(索引与查询优化)

    原文:提升mysql服务器性能(索引与查询优化) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/details/90138407 ...

  4. 提升mysql服务器性能(分库、分片与监控)

    原文:提升mysql服务器性能(分库.分片与监控) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/details/90145515 ...

  5. 高性能MySQL(三):服务器性能剖析

    select * from c LEFT JOIN c100w on c.id=c100w.id; -- 联合查询 show PROFILES; -- 查看查询耗时 select * from c; ...

  6. MySQL服务器基准测试

    一.基准测试简介 1.什么是基准测试 数据库的基准测试是对数据库的性能指标进行定量的.可复现的.可对比的测试. 基准测试与压力测试 基准测试可以理解为针对系统的一种压力测试.但基准测试不关心业务逻辑, ...

  7. 11 MySQL之性能优化

    01-优化简介 MySQL数据库优化是多方面的,原则是减少系统瓶颈,减少资源的占用,增加系统的反应速度. 1.通过优化文件系统,提高磁盘I\O的速写速度: 2.通过优化操作系统的调度策略,提高MySQ ...

  8. MySQL 高级性能优化架构 千万级高并发交易一致性系统基础

    一.MySQL体系架构 由图,可以看出MySQL最上层是连接组件.下面服务器是由连接池.管理服务和工具组件.SQL接口.查询解析器.查询优化器.缓存.存储引擎.文件系统组成. 1.连接池 管理.缓冲用 ...

  9. MySQL性能剖析工具(pt-query-digest)【转】

    这个工具同样来自percona-toolkit 该工具集合的其他工具 MySQL Slave异常关机的处理 (pt-slave-restart)  验证MySQL主从一致性(pt-table-chec ...

随机推荐

  1. Elasticsearch安装及遇到的问题(CentOS 7.3 64位)

    Elasticsearch安装 使用root用户创建一个其他用户,(elasticsearch不能在root账户下安装) # 添加一个名字是es工作组 groupadd es # 添加用户es设置密码 ...

  2. Samba服务问答

    1. samba服务用在什么地方?samba服务用于把Linux服务器上的文件或者打印接共享给windows或者Linux. 2. 在samba服务的配置文件中,[global]配置部分的securi ...

  3. using 用法拾忆

    using 用法主要包括三种: 1.引用外部命名空间以及外部命名空间中定义的类型(指令) 2.创建命名空间别名,避免因名称相同造成的冲突(指令) 3.定义资源使用范围,在范围结束后释放资源对象(语句) ...

  4. Fiddler用法整理

    目 录 1 Fiddler的基本介绍 1.1 下载安装 1.2 适用平台 2 Fiddler的工作原理 3 同类工具 4 捕获非IE浏览器的会话 5 捕获不同请求的设置方法 5.1 Web HTTPS ...

  5. AppDomain (转)

    AppDomain是CLR的运行单元,它可以加载Assembly.创建对象以及执行程序.AppDomain是CLR实现代码隔离的基本机制. 每一个AppDomain可以单独运行.停止:每个AppDom ...

  6. 实体模型集合对象转换为VO对象集合

    例如: 数据库中查出来的数据为 List<RptDayMonthTarget> List<RptDayMonthTarget> list = targetService.sel ...

  7. pg_ctl - 启动,停止和重启 PostgreSQL 服务器

    SYNOPSIS pg_ctl start [ -w ] [ -s ] [ -D datadir] [ -l filename] [ -o options] [ -p path] pg_ctl sto ...

  8. Codeforces Round #425 (Div. 2) - A

    题目链接:http://codeforces.com/contest/832/problem/A 题意:有n个棍子,两个人轮流取这些棍子,每个人每次只能去恰好k个棍子(不足k个则不能取),问先手取的棍 ...

  9. 【转】SPI FLASH与NOR FLASH的区别 详解SPI FLASH与NOR FLASH的不一样

    转自:http://m.elecfans.com/article/778203.html 本文主要是关于SPI FLASH与NOR FLASH的相关介绍,并着重对SPI FLASH与NOR FLASH ...

  10. php session生存周期

    今天在我的微博(Laruence)上发出一个问题: 我在面试的时候, 经常会问一个问题: “如何设置一个30分钟过期的Session?”, 大家不要觉得看似简单, 这里面包含的知识挺多, 特别适合考察 ...