本文基于Percona Toolkit 3.2.0,理论支持所有版本。
Percona Toolkit是一款MySQL世界里面非常实用的工具套件,如何安装它。
不支持。详见https://forums.percona.com/discussion/52503/percona-toolkit-for-windows
支持的操作系统主要有:
可参考 https://blog.csdn.net/zyx_ly/article/details/88958352 的说明查看自己用的是哪个Linux发行版。
官方宣称,理论上Percona Toolkit也能支持其他使用基于Deb或RPM的Linux操作系统,但只有上面这些系统经过了测试。详见 https://www.percona.com/doc/percona-toolkit/LATEST/installation.html
这一步主要是配置Percona的仓库,配置好之后,Percona的相关库都可以从该仓库里下载。
可以通过以下命令查看Linux发行版
cat /etc/issue
基于Deb的Linux操作系统
例如:Debain、Ubuntu等
# 备份源配置文件
mv /etc/apt/sources.list /etc/apt/sources.list.bak
# 使用中科大源
echo 'deb http://mirrors.ustc.edu.cn/debian/ buster main
deb-src http://mirrors.ustc.edu.cn/debian/ buster main
deb http://mirrors.ustc.edu.cn/debian-security buster/updates main
deb-src http://mirrors.ustc.edu.cn/debian-security buster/updates main
deb http://mirrors.ustc.edu.cn/debian/ buster-updates main
deb-src http://mirrors.ustc.edu.cn/debian/ buster-updates main' > /etc/apt/sources.list
# 更新
apt-get update
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
sudo dpkg -i percona-release_latest.generic_all.deb
/etc/apt/sources.list.d/percona-release.list
中找到Percona Toolkit仓库设置。基于RPM的Linux操作系统
例如:Red Hat Enterprise Linux、CentOS等
sudo yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
基于Deb的Linux操作系统
sudo apt-get install percona-toolkit
基于RPM的Linux操作系统
sudo yum install percona-toolkit
brew install percona-toolkit
官方文档:pt-query-digest
分析日志(包括binlog、General log、slowlog)、processlist以及tcpdump中的查询,从而,帮助我们做SQL优化。就目前来说,很多企业用它来分析慢查询日志
pt-query-digest [OPTIONS] [FILES] [DSN]
--create-review-table 当使用--review参数把分析结果输出到表中时,如果没有表就自动创建
--create-history-table 当使用--history参数把分析结果输出到表中时,如果没有表就自动创建
--filter 输出符合条件的内容
--limit 限制输出的百分比或数量。可指定百分比或数字,例如90%表示按响应时间从小到大排序,输出90%的结果;20表示输出最慢的20条
--host 指定MySQL地址,也可用-h指定
--port 指定MySQL端口
--user 指定MySQL用户名,也可用-u指定
--password 指定MySQL密码,也可用-p指定
--history 将分析结果保存到表中,分析结果比较详细,下次再使用--history时,如果存在相同的语句,且查询所在的时间区间和历史表中的不同,可通过查询同一CHECKSUM来比较某类型查询的历史变化
--review 将分析结果保存到表中,从而方便未来review。这个分析只是对查询条件进行参数化,一个类型的查询一条记录,比较简单。当下次使用--review时,如果存在相同的语句分析,就不会记录到数据表中
--output 指定将结果输出输出到哪里,值可以是report(标准分析报告)、slowlog(Mysql slow log)、json、json-anon,一般使用report,以便于阅读
--since 指定分析的起始时间,值为字符串,可以是指定的某个”yyyy-mm-dd [hh:mm:ss]”格式的时间点,也可以是简单的一个时间值:s(秒)、h(小时)、m(分钟)、d(天),如12h就表示从12小时前开始统计
--until 指定分析的截止时间,配合--since可以分析一段时间内的慢查询
A 指定字符集
D 指定连接的数据库
P 连接数据库端口
S 连接Socket file
h 连接数据库主机名
p 连接数据库的密码
t 使用--review或--history时把数据存储到哪张表里
u 连接数据库用户名
DSN使用key=value的形式配置;多个DSN使用,分隔
# 展示slow.log中最慢的查询的报表
pt-query-digest slow.log
# 分析最近12小时内的查询
pt-query-digest --since=12h slow.log
# 分析指定范围内的查询
pt-query-digest slow.log --since '2020-06-20 00:00:00' --until '2020-06-25 00:00:00'
# 把slow.log中查询保存到query_history表
pt-query-digest --user=root --password=root123 --review h=localhost,D=test,t=query_history --create-review-table slow.log
# 连上localhost,并读取processlist,输出到slowlog
pt-query-digest --processlist h=localhost --user=root --password=root123 --interval=0.01 --output slowlog
# 利用tcpdump获取MySQL协议数据,然后产生最慢查询的报表
# tcpdump使用说明:https://blog.csdn.net/chinaltx/article/details/87469933
tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt
pt-query-digest --type tcpdump mysql.tcp.txt
# 分析binlog
mysqlbinlog mysql-bin.000093 > mysql-bin000093.sql
pt-query-digest --type=binlog mysql-bin000093.sql
# 分析general log
pt-query-digest --type=genlog localhost.log
在Percona官方 https://www.percona.com/blog/2012/08/31/visualization-tools-for-pt-query-digest-tables/ 有介绍两款工具:
## 开启慢SQL日志
set global slow_query_log = 'ON';
set global log_output = 'FILE,TABLE';
set global long_query_time = 0.001;
## 查询慢SQL日志是否开启,以及慢SQL日志文件存放位置
SHOW VARIABLES LIKE '%slow%';
-- slow_query_log ON
-- slow_query_log_file /var/lib/mysql/es23-slow.log
SHOW VARIABLES LIKE 'log_output';
-- log_output FILE,TABLE
## 进入文件目录
cd /var/lib/mysql/
## 使用pt-query-digest
pt-query-digest es23-slow.log
生成了以下的报表
*******************************************************************
Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER
possibly with SSL_ca_file|SSL_ca_path for verification.
If you really don't want to verify the certificate and keep the
connection open to Man-In-The-Middle attacks please set
SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************
at /usr/bin/pt-query-digest line 12058.
*******************************************************************
Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER
possibly with SSL_ca_file|SSL_ca_path for verification.
If you really don't want to verify the certificate and keep the
connection open to Man-In-The-Middle attacks please set
SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************
at /usr/bin/pt-query-digest line 12058.
# A software update is available:
-- 报表该有的信息
# 110ms user time, 30ms system time, 29.68M rss, 243.06M vsz
-- 分析时间
# Current date: Thu Jun 1 19:08:31 2023
-- 分析机器
# Hostname: es23
-- 分析文件
# Files: es23-slow.log
-- 分析总SQL,唯一的SQL条数
# Overall: 145 total, 40 unique, 0.00 QPS, 0.00x concurrency _____________
# Time range: 2023-03-26T22:08:18 to 2023-04-07T17:49:49
# Attribute total min max avg 95% stddev median
# ============ ======= ======= ======= ======= ======= ======= =======
-- 执行时间
# Exec time 6s 336us 6s 44ms 7ms 453ms 1ms
-- 锁持有时间
# Lock time 316us 0 28us 2us 5us 3us 1us
-- 向客户端发送的数据量
# Rows sent 6.02M 0 4.86M 42.52k 487.09 400.07k 16.81
-- 扫描的数据量
# Rows examine 6.40M 0 5.15M 45.22k 1.53k 419.77k 964.41
-- 查询大小
# Query size 17.04k 11 570 120.37 212.52 104.38 97.36
-- 查询排序
# Profile
-- 针对SQL生成的唯一标识 SQL花费总时间 这条SQL执行时间占用总时间百分比 执行次数 平均每次花费时间 这条SQL执行时间趋向平均值的方差,越小表示该条SQL越稳定 该SQL
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================== ============= ===== ====== ===== ===============
# 1 0xE418612AF8CD4C2D 5.5196 85.6% 1 5.5196 0.00 SELECT employees.employees employees.salaries
# 2 0x633F5856DF702BD1 0.5233 8.1% 3 0.1744 0.00 SELECT employees
# 3 0x24D0922230C4DAE5 0.1483 2.3% 1 0.1483 0.00 SELECT employees.employees
# MISC 0xMISC 0.2593 4.0% 140 0.0019 0.0 <37 ITEMS>
-- 针对某条SQL分析
-- ID
# Query 1: 0 QPS, 0x concurrency, ID 0xE418612AF8CD4C2D at byte 11646 ____
# This item is included in the report because it matches --limit.
-- 方差
# Scores: V/M = 0.00
# Time range: all events occurred at 2023-04-07T11:23:38
-- 详细信息
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 0 1
# Exec time 85 6s 6s 6s 6s 6s 0 6s
# Lock time 0 3us 3us 3us 3us 3us 0 3us
# Rows sent 80 4.86M 4.86M 4.86M 4.86M 4.86M 0 4.86M
# Rows examine 80 5.15M 5.15M 5.15M 5.15M 5.15M 0 5.15M
# Query size 2 450 450 450 450 450 0 450
# String:
-- 数据库
# Databases employees
-- 数据库实例
# Hosts 192.168.218.1
-- 哪个用户执行
# Users imooc
-- 执行时间分布
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s ################################################################
# 10s+
-- 该SQL相关的表
-- 同时pt-query-digest贴心地展示了SHOW和EXPLAIN语句,这样,如果这条SQL性能瓶颈又想查看表的状态就可以直接COPY执行
# Tables
# SHOW TABLE STATUS FROM `employees` LIKE 'employees'\G
# SHOW CREATE TABLE `employees`.`employees`\G
# SHOW TABLE STATUS FROM `employees` LIKE 'salaries'\G
# SHOW CREATE TABLE `employees`.`salaries`\G
# EXPLAIN /*!50100 PARTITIONS*/
-- 原始的SQL
select '10001' AS `emp_no`,'1953-09-02' AS `birth_date`,'Georgi' AS `first_name`,'Facello' AS `last_name`,'M' AS `gender`,'1986-06-26' AS `hire_date`,'0' AS `first_name_hash`,`employees`.`s`.`emp_no` AS `emp_no`,`employees`.`s`.`salary` AS `salary`,`employees`.`s`.`from_date` AS `from_date`,`employees`.`s`.`to_date` AS `to_date` from `employees`.`employees` `e` left join `employees`.`salaries` `s` on((`employees`.`s`.`emp_no` = 10001)) where true\G
-- 另一条SQL
# Query 2: 0.00 QPS, 0.00x concurrency, ID 0x633F5856DF702BD1 at byte 8552
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2023-03-26T22:11:49 to 2023-04-07T10:34:39
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 2 3
# Exec time 8 523ms 165ms 192ms 174ms 189ms 12ms 163ms
# Lock time 2 7us 1us 3us 2us 2us 0 2us
# Rows sent 14 878.98k 292.99k 292.99k 292.99k 292.99k 0 292.99k
# Rows examine 13 878.98k 292.99k 292.99k 292.99k 292.99k 0 292.99k
# Query size 0 69 23 23 23 23 0 23
# String:
# Databases employees
# Hosts 192.168.218.1
# Users imooc
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms ################################################################
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `employees` LIKE 'employees'\G
# SHOW CREATE TABLE `employees`.`employees`\G
# EXPLAIN /*!50100 PARTITIONS*/
select * from employees\G
# Query 3: 0 QPS, 0x concurrency, ID 0x24D0922230C4DAE5 at byte 23865 ____
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: all events occurred at 2023-04-07T15:15:24
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 0 1
# Exec time 2 148ms 148ms 148ms 148ms 148ms 0 148ms
# Lock time 1 5us 5us 5us 5us 5us 0 5us
# Rows sent 4 292.99k 292.99k 292.99k 292.99k 292.99k 0 292.99k
# Rows examine 4 292.99k 292.99k 292.99k 292.99k 292.99k 0 292.99k
# Query size 0 33 33 33 33 33 0 33
# String:
# Databases employees
# Hosts 192.168.218.1
# Users imooc
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms ################################################################
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `employees` LIKE 'employees'\G
# SHOW CREATE TABLE `employees`.`employees`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM employees.employees\G
怎么使用上面的报表呢?
首先,可以使用概要信息,主要关注R/Call,指这条SQL平均每次花费时间;Calls,这个值越多表示调用越频繁,调用越频繁的慢SQL优化的价值就越大;Response time,比例越大说明这条SQL越重要,优化价值越高。找到需要优化的SQL的Query ID再在报表中查找就可针对分析。
pt-query-digest --user=imooc --password=Imooc@123456 --review h=localhost,D=test,t=query_history --create-review-table es23-slow.log
无法连接数据库,并报类似如下的异常:
DBI connect(';host=localhost;mysql_read_default_group=client','root',...) failed: Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory at /usr/bin/pt-query-digest line 1001.
高版本的MySQL使用caching_sha2_password,由于目前Percona Toolkit中的部分工具暂不支持caching_sha2_password导致的。
mysql> ALTER USER 你的用户@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';
例如:
ALTER USER root@'localhost' IDENTIFIED WITH mysql_native_password BY 'root123';
[mysqld] default_authentication_plugin=mysql_native_password
将日志分析结果存入表中的好处:可以每一个月执行一次这个命令,后续做统计
官方文档:pt-index-usage
通过日志文件分析查询,并分析查询如何使用索引
pt-index-usage [OPTIONS] [FILES]
--drop 打印建议删除的索引,取值primary、unique、non-unique、all。默认值non-unique,只会打印未使用的二级索引
--databases 只分析指定数据库的索引,多个库用,分隔
--tables 只分析指定表的索引,多张表用,分隔
--progress 打印执行进度
--host 指定MySQL地址,也可用-h指定
--port 指定MySQL端口
--user 指定MySQL用户名,也可用-u指定
--password 指定MySQL密码,也可用-p指定
DSN使用key=value的形式配置;多个DSN使用,分隔
A 指定字符集
D 指定连接的数据库
h 连接数据库主机名
p 连接数据库的密码
P 连接数据库端口
S 连接Socket file
u 连接数据库用户名
# 读取slow.log,并连上localhost,去分析有哪些索引是可以删除的
pt-index-usage slow.log --user=root --password=root123 --host=localhost --port=
# 读取slow.log,并连上localhost,只分析employees库中,有有哪些索引是可以删除的
pt-index-usage slow.log --user=root --password=root123 --host=localhost --databases=employees
注意点
此工具使用MySQL资源比较多,因此,在使用此工具时候:
此工具分析大文件比较慢,使用时需注意这点,并做一定处理(比如把遗留的超大的慢查询日志先删除,而可以新建一个慢查询日志,并运行一段时间后用pt-index-usage分析)
由于pt-index-usage只会扫描慢查询,而非所有的查询,所以有可能某个索引在慢查询日志中未使用,但其实还是被使用了的(只是使用这个索引的SQL并非慢查询)。因此:
正式删除之前,应当先review下,确保可以删除该索引后再操作,避免发生问题
对于MySQL 8.0及更高版本,善用“不可见索引”,进一步降低风险。
不可见索引是不会被MySQL优化器使用的,可以把要删除的索引设置为不可见索引,优化器就会忽略该索引,避免误删需要的索引
具体操作:
-- 设置成不可见
ALTER TABLE `employees` ALTER INDEX `employees_first_name_last_name_index` invisible;
-- 设置成可见
ALTER TABLE `employees` ALTER INDEX `employees_first_name_last_name_index` visible;
pt-duplicate-key-checker :可以帮助我们找到重复的索引或外键,使用方式基本类似。
pt-index-usage es23-slow.log --user=imooc --password=Imooc@123456 --host=localhost
ALTER TABLE `employees`.`employees` DROP KEY `employees_first_name_last_name_index`; -- type:non-unique
ALTER TABLE `employees`.`salaries` DROP KEY `salaries_emp_no_salary_index`; -- type:non-unique
可以看到结果中对冗余索引生成了删除语句
官方文档:pt-variable-advisor
分析MySQL变量,并对可能出现的问题提出建议
执行 SHOW VARIABLES
,并分析哪些变量的值设置不合理,给出建议
pt-variable-advisor [OPTIONS] [DSN]
--source-of-variable 指定变量来源,可选mysql/none或者文件
--user 指定MySQL用户名,也可用-u指定
--password 指定MySQL密码,也可用-p指定
A 指定字符集
D 指定连接的数据库
h 连接数据库主机名
p 连接数据库的密码
P 连接数据库端口
S 连接Socket file
u 连接数据库用户名
DSN使用key=value的形式配置;多个DSN使用,分隔
# 连接上localhost:3306,并分析变量
pt-variable-advisor localhost --user=root --password=root123
pt-variable-advisor P=3306,u=root,p=root123 localhost:3306
# 先将show global variables生成文件,然后用pt-variable-advisor分析文件
mysql -uroot -proot123 -e'show global variables' > /root/vars.txt
pt-variable-advisor --source-of-variables /root/vars.txt
# 分析数据库变量
pt-variable-advisor localhost --user=imooc --password=Imooc@123456
# WARN delay_key_write: MyISAM index blocks are never flushed until necessary.
# WARN key_buffer_size: The key buffer size is set to its default value, which is not good for most production systems.
# NOTE sort_buffer_size-1: The sort_buffer_size variable should generally be left at its default unless an expert determines it is necessary to change it.
# WARN expire_logs_days: Binary logs are enabled, but automatic purging is not enabled.
# NOTE innodb_data_file_path: Auto-extending InnoDB files can consume a lot of disk space that is very difficult to reclaim later.
# NOTE innodb_flush_method: Most production database servers that use InnoDB should set innodb_flush_method to O_DIRECT to avoid double-buffering, unless the I/O system is very low performance.
-- 直接将log_output设置输出到表是很影响性能的
# WARN log_output: Directing log output to tables has a high performance impact.
# WARN myisam_recover_options: myisam_recover_options should be set to some value such as BACKUP,FORCE to ensure that table corruption is noticed.
# 先将show global variables生成文件,然后用pt-variable-advisor分析文件
mysql -uimooc -pImooc@123456 -e'show global variables' > /root/vars.txt
pt-variable-advisor --source-of-variables /root/vars.txt
# WARN delay_key_write: MyISAM index blocks are never flushed until necessary.
# WARN key_buffer_size: The key buffer size is set to its default value, which is not good for most production systems.
# NOTE sort_buffer_size-1: The sort_buffer_size variable should generally be left at its default unless an expert determines it is necessary to change it.
# WARN expire_logs_days: Binary logs are enabled, but automatic purging is not enabled.
# NOTE innodb_data_file_path: Auto-extending InnoDB files can consume a lot of disk space that is very difficult to reclaim later.
# NOTE innodb_flush_method: Most production database servers that use InnoDB should set innodb_flush_method to O_DIRECT to avoid double-buffering, unless the I/O system is very low performance.
# WARN log_output: Directing log output to tables has a high performance impact.
# WARN myisam_recover_options: myisam_recover_options should be set to some value such as BACKUP,FORCE to ensure that table corruption is noticed.
这也可以告诉我们哪些变量是不合理的,和上面一样
官方文档:pt-online-schema-change
MySQL从5.6开始,已支持online r功能,pt-online-schema-change越来越弱化了。
- 有关Online DDL,可详见 Online DDL Operations
- 有关online DDL和pt-online-schema-change之间的对比详见《 MySQL ONLINE DDL 和PT-ONLINE-SCHEMA-CHANGE对比 》
在线修改表结构,无需锁表地ALTER表结构
pt-online-schema-change [OPTIONS] DSN
--dry-run 创建并修改新表的结构,但不会创建触发器、拷贝旧表数据也不会替换旧表
--execute 如果指定该选项,则会修改表结构,否则只会做一些安全检查
--charset 指定编码
--alter 修改表结构的语句(其实就是你alter table语句,去掉alter table后剩下的部分),多条语句使用,分隔。该选项有一些限制,详见 https://www.percona.com/doc/percona-toolkit/3.0/pt-online-schema-change.html#cmdoption-pt-online-schema-change-alter
--no-version-check 是否检查版本
--alter-foreign-keys-method 处理带有外键约束的表,以保证它们可以引用到正确的表。取值:auto(自动选择最佳策略)、rebuild_constraints(适用于删除和重新添加引用新表的外键约束)、drop_swap(禁用外键检查,然后在重命名新表之前将其删除)、none(无)
A 指定字符集
D 指定连接的数据库
h 连接数据库主机名
p 连接数据库的密码
P 连接数据库端口
S 连接Socket file
t 想要alter的表
u 连接数据库用户名
DSN使用key=value的形式配置;多个DSN使用,分隔
# 为employees库的employees表添加字段my_test_column
pt-online-schema-change -uroot -proot123 --alter='add column my_test_column int' --alter-foreign-keys-method=rebuild_constraints --execute D=employees,t=employees --charset=utf8mb4
# 修改字段
pt-online-schema-change -uroot -proot123 --alter='modify column my_test_column bigint(25)' --alter-foreign-keys-method=rebuild_constraints --execute D=employees,t=employees --charset=utf8mb4
# 添加索引
pt-online-schema-change -uroot -proot123 --alter='add key indx_my_test_column(my_test_column)' --alter-foreign-keys-method=rebuild_constraints --execute D=employees,t=employees
# 删除索引
pt-online-schema-change -uroot -proot123 --alter='drop key indx_my_test_column' --alter-foreign-keys-method=rebuild_constraints --execute D=employees,t=employees
# 删除字段
pt-online-schema-change -uroot -proot123 --alter='drop column my_test_column int' --alter-foreign-keys-method=rebuild_constraints --execute D=employees,t=employees
# 展示系统概要信息
pt-summary
# 展示MySQL相关的概要信息
pt-mysql-summary --user=root --password=root123 --host=localhost --port=3306
# 把explain的结果转换成树形展示(在早期MySQL中,没有explain format=tree时,比较有用,可以增强explain的可读性)
mysql -uroot -proot123 -e "explain select * from employees.employees" > test-explain.sql
pt-visual-explain --host=localhost --user=root --password=root123 test-explain.sql
无法连接数据库,并报类似如下的异常:
DBI connect(';host=localhost;mysql_read_default_group=client','root',...) failed: Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory at /usr/bin/pt-query-digest line 1001.
这是由于目前Percona Toolkit中的部分工具暂不支持caching_sha2_password导致的。
解决方案有两种:
mysql> ALTER USER 你的用户@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';
例如:
ALTER USER root@'localhost' IDENTIFIED WITH mysql_native_password BY 'root123';
[mysqld] default_authentication_plugin=mysql_native_password