DBA数据库笔记之(五)提升MySQL维护效率-PT工具

DBA必备的常用开发语言连接MySQL

使用Shell如何对MySQL进行操作

  • 创建测试用户和测试表
create user 'shell_rw'@'%' identifiled by '123456';
grant create,alter,insert,delete,select,update,show view on *.* to 'shell_rw'@'%';
# 创建测试表
... ... 
  • 通过linux命令连接MySQL
# 通过命令行访问数据库 -e "sql语句"
mysql -ushell_rw -p'123456' -e "show databases"
mysql -ushell_rw -p'123456' -e "show tables"
  • 通过linux命令行查询MySQL数据
# martin数据库名
mysql -ushell_rw -p'123456' martin -e "select * from t1 limit 1"
  • 在Shell脚本里执行MySQL增删查改
vim mysql_crud.sh

#!/bin/bash
# 设置MySQL连接信息
#设置MySQL连接信息
mysql_host='localhost'
mysql_user='shell_rw!'
mysql_pass='Idyq8_al'
mysql_db='martin'
# 执行写入操作
mysql -h"$mysql_host" -u"$mysql_user" -p"$mysql_pass" $mysql_db -e "insert into productes(name,price) values ('apple'10.50)"
# 查询数据
mysql -h"$mysql_host" -u"$mysql_user" -p"$mysql_pass" $mysql_db -e "select * from products where name='apple'"
# 修改数据
mysql -h"$mysql_host" -u"$mysql_user" -p"$mysql_pass" $mysql_db -e "update products set price=12.5 where name='apple'"
# 删除数据
mysql -h"$mysql_host" -u"$mysql_user" -p"$mysql_pass" $mysql_db -e "delete from products where name='apple'"
  • 用ChatGPT帮忙写Shell连接MySQL的脚本

编写一个Shell脚本,查询MySQL8.0当前活跃连接,并导入到当前路径下的文件下,文件名是processlist,当前时间.log,比如processlist_2030101080808.log

  • 用ChatGPT帮忙写多个MySQL参数查询的脚本

ip.txt中,每一行存放MySQL的IP地址、用户名和密码,形式如下,请编写一个shell脚本,提示我们
输入变量名,就可以把所有MySQL的IP,这个变量和变量在MySQL中对应的值展示出192.168.152.70,read_only,xxUagc8_6
192.168152.71,read_only,dagdacag6

  • 用ChatGPT帮忙写统计MySQL信息的shell脚本

编辑一个shell脚本
脚本运行10秒
统计10秒前后MySQL8.0的查询次数 (Queries的变化)
以及这10秒产生的慢查询数量 (Slow_queries的变化)
需要注意这些值,都是在执行 SHOW GLOBAL STATUS like xxx;之后的第二行,需要过滤出来
用户名和密码在脚本前面定义,后面通过用户名密码的变量来连接MySQL

  • 用ChatGPT帮忙写业务表统计信息

编辑一个shell脚本
查information_schema.tables
统计某个库所有表的预估数据量
自增值
存储引擎
每一行展示一张表的信息

使用Python如何对MySQL进行操作

  1. 安装python
  2. 安装VScode

python操作MySQL数据库

使用Go如何对MySQL进行操作

go教程
Go操作MySQL

详解SQL注入及分析存在哪些风险

select * from users where username='user111' and password='pass111';
  1. 使用or的SQL注入
# pass111 变成 ' or 'a'='a
select * from users where username='user111' and password=' ' or 'a'='a ';
  1. 使用union的SQL注入
# 输入 ' union select * from users;-- 
select * from users where username=' ' union select * from users;--' and password='pass111';
  • 数据泄露
  • 篡改数据
  • 服务中断

SQL注入演示实验

... ...

如何预防SQL注入

  1. 代码中使用预编译形式
  2. 对输入进行校验和过滤
  3. 权限最小化
  4. 关注自己使用的框架或者包是否存在漏洞
  5. 审计和监控

DBA必备常用PT工具的用法

PT工具 作用
pt-online-schema-change 不锁表更改表结构
pt-query-digest 分析MySQL查询
pt-kill kill掉符合特定条件的MySQL查询
pt-table-checksum 验证MySQL复制完整性
pt-table-sync 同步MySQL表数据

pt-osc在线修改表结构

# 选择版本,对应系统
wget https://downloads.percona.com/downloads/percona-toolkit/3.5.5/binary/redhat/7/x86_64/percona-toolkit-3.5.5-1.el7.x86_64.rpm?_gl=1*1ec2jux*_gcl_au*ODkzMjE1NzE2LjE2OTcxNjY2MzE.
yum install percona-toolkit-3.5.5-1.el7.x86_64.rpm

# 查看是否安装成功
pt-online-schema-change --version
  • 创建测试用户和测试表
# 使用 mysql_native_password
create user 'pt_osc'@'localhost' identifiled with mysql_native_password by '123456';
grant create,drop,alter,insert,delete,select,update,process,replication slave,trigger on *.* to 'pt_osc'@'localhost';
# 创建测试表,测试数据
  • 哪些版本建议使用pt-osc

MySQL5.7及之前的版本;MySQL8.0.12以及之后的版本InnoDB原生支持快速加列的功能

  • pt-osc原理分析
    用pt-osc增加字段
set global general_log=on;
# 实时打印操作的日志
tail -f /data/mysql/log/mysql-general.log

# 另一窗口
# D=martin 数据库名,t=users_info 表名
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "add column age int" --execute D=martin,t=users_info
  • 查看general_log,原理总结
  1. 创建一张与原始表结构相同的临时表
  2. 然后对临时表进行表结构变更
  3. 通过触发器实现增量数据处理
  4. 将原始表中的数据复制到新表中
  5. 把原始表重命名为_x_old,将临时表重命名为x
  6. 删除_xxx_old表,删除3个触发器
  7. 表结构变更完成

pt-osc更多用法

  • 删除列
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "drop column age" --execute D=martin,t=users_info
  • 修改列类型
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "modify column email varchar(100)" --execute D=martin,t=users_info
  • 修改列名
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "change column name user_name varchar(50)" --execute --no-check-alter D=martin,t=users_info
  • 添加索引
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "add index index_user_name (user_name)" --execute D=martin,t=users_info
  • 删除索引
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "drop index index_user_name" --execute D=martin,t=users_info
  • 添加唯一索引的问题
# 如果数据存在相同的数据,然后添加唯一索引,则可能导致数据丢失
pt-online-schema-change -u pt_osc -p '123456' -S /tmp/mysql.sock --alter "add unique key unique_user_name (user_name)" --execute --no-check-unique-key-change  D=martin,t=users_info
  • 使用pt-osc的注意事项
  1. 表必须有主键或者唯一索引
  2. 保证足够空间
  3. 原表上不能有触发器存在

pt-query-digest分析慢查询

  • SQL指纹
select * from user where user_name='aaa';
select * from user where user_name='bbb';
# 则这两条sql语句拥有相同的指纹
select * from user where user_name= ?
  • 用pt-query-digest分析慢查询
# 查看慢查询是否开启
show global variables like "slow_query%";
# /data/mysql/log/mysql-slow.log 慢查询日志文件
pt-query-digest /data/mysql/log/mysql-slow.log
# 将结果导入文件
pt-query-digest /data/mysql/log/mysql-slow.log > slowquery_digest.log
# 查看分析报告
cat slowquery_digest.log
  • 分析24小时以内的慢查询
pt-query-digest --since=24h /data/mysql/log/mysql-slow.log > 24h_slowquery_digest.log
  • 指定时间范围
pt-query-digest /data/mysql/log/mysql-slow.log  --since '2023-07-11 23:00:00' --until '2023-07-11 23:59:59'  > time_range_slowquery_digest.log
  • 某个用户执行的慢查询
create user 'martin'@'localhost' identifiled with mysql_native_password by '123456';
grant select on *.* to 'martin'@'localhost';
# 执行慢查询测试
mysql -umartin -p'123456' -e "select sleep(2)";
# 分析
pt-query-digest --filter '($event->{user} || "" ) =~ m/^martin/i' /data/mysql/log/mysql-slow.log > martin_slowquery_digest.log
  • 把慢查询结果存放在MySQL中
create user 'slowlog_rw'@'localhost' identifiled with mysql_native_password by '123456';
grant all on slow_log.* to 'slowlog_rw'@'localhost';
# 创建库
create database slow_log;
pt-query-digest --user=slowlog_rw --password=123456 -S /tmp/mysql.sock --review D=slow_log,t=global_query_review --history D=slow_log,t=global_query_review_history /data/mysql/log/mysql-slow.log 
  • 分析binlog
mysqlbinlog /data/mysql/binlog/mysql-bin.000028 -vv > binlog.sql
pt-query-digest --type=binlog binlog.sql > binlog_digest.log
cat binlog_digest.log
  • 分析General Log
# 查看general log是否开启
show global variables like "general%";
pt-query-digest --type=genlog /data/mysql/log/mysql-general.log > general_digest.log
cat general_digest.log

pt-kill来kill掉一些垃圾SQL

  • 创建测试用户
create user 'dba'@'localhost' identifiled with mysql_native_password by '123456';
grant all on *.* to 'dba'@'localhost';
  • 打印但不kill问题SQL
# --busy-time=10 查过这个时间就打印;--interval=10 检测的时间间隔10s
pt-kill --user=dba --password='123456' --socket=/tmp/mysql.sock --busy-time=10 --interval=10 --print
  • kill掉问题SQL
pt-kill --user=dba --password='123456' --socket=/tmp/mysql.sock --busy-time=10 --interval=10 --print --kill
  • 后台运行
# --daemonize 后台运行
pt-kill --user=dba --password='123456' --socket=/tmp/mysql.sock --busy-time=10 --interval=10 --print --kill --daemonize
ps -ef | grep pt-kill 
  • 打印日志
pt-kill --user=dba --password='123456' --socket=/tmp/mysql.sock --busy-time=10 --interval=10 --print --kill --daemonize --log=/data/ptkill.log
tail -f /data/ptkill.log
  • 根据用户去杀会话
pt-kill --user=dba --password='123456' --socket=/tmp/mysql.sock --busy-time=10 --interval=10 --print --kill --match-user 'martin'

pt-table-checksum进行主从一致性排查

  • pt-table-checksum特点
  1. 可以用来校验大表
  2. pt-table-checksum的保护策略
  3. 监控从库
  • 创建测试用户
# 这个用户要连接上主库和从库
create user 'dba'@'192.168.%' identifiled with mysql_native_password by '123456';
grant all on *.* to 'dba'@'192.168.%';
  • 执行一致性校验
pt-table-checksum --no-check-binlog-format --host=192.168.12.161 --user=dba --password='123456' --socket=/tmp/mysql.sock
  • 只检查指定库
pt-table-checksum --no-check-binlog-format --host=192.168.12.161 --user=dba --password='123456' --socket=/tmp/mysql.sock --databases=martin
  • 只检查指定表
pt-table-checksum --no-check-binlog-format --host=192.168.12.161 --user=dba --password='123456' --socket=/tmp/mysql.sock --databases=martin --tables=pt_checksum
  • 只检查某些字段
pt-table-checksum --no-check-binlog-format --host=192.168.12.161 --user=dba --password='123456' --socket=/tmp/mysql.sock --databases=martin --tables=pt_checksum --columns=nickname
  • 把结果写到表中
create database checksum;
pt-table-checksum --no-check-binlog-format --host=192.168.12.161 --user=dba --password='123456' --socket=/tmp/mysql.sock --databases=martin --replicate=checksum.result
# 查询结果
select * from checksum.result;

pt-table-sync进行主从一致性的修复

  • 输出修复语句
show slave hosts;
# 打印出修复语句;--replicate=把校验结果记录到percona.checksums表里面;--sync-to-master 修复指定的从库
pt-table-sync --print --replicate=percona.checksums --sync-to-master  h=192.168.12.162,u=dba,p=123456
# 输出需要在从库执行的修复语句,解决主从不一致的情况
  • 输出指定库的修复语句
pt-table-sync --print --replicate=percona.checksums --sync-to-master  h=192.168.12.162,u=dba,p=123456 --databases=martin
  • 执行修复操作
pt-table-sync --execute --replicate=percona.checksums --sync-to-master  h=192.168.12.162,u=dba,p=123456 --databases=martin

pt-archiver来进行数据归档

  • pt-archiver的作用
  1. 清理过期的数据
  2. 归档数据
  • 创建测试用户
create user 'dba'@'192.168.%' identifiled with mysql_native_password by '123456';
grant all on *.* to 'dba'@'192.168.%';
  • 创建测试表和数据
    ... ...
  • 全表归档不删除原表数据
# --source 要归档的表;--dest 存放的实例;--where '1=1' 归档全表数据;--progress 1000每一万行打印进度信息;--limit=10000 一次查询一万行;--txn-size=10000设置一万行为一次事务提交一次;--no-safe-auto-increment 不加这个参数,最大的记录归档不了,加了则可能MySQL重启之后再次归档出现主键冲突问题;--statistics 搜集并打印搜集的数据;--no-delete 不删除原表数据

pt-archiver --source h=192.168.12.161,u=dba,p='123456',D=martin,t=archiver_test --dest h=192.168.12.162,u=dba,p='123456',D=archiver_db,t=archiver_test --where '1=1' --progress 1000 --limit=10000 --txn-size=10000 --no-safe-auto-increment --statistics --no-delete
  • 全部归档删除原表数据
pt-archiver --source h=192.168.12.161,u=dba,p='123456',D=martin,t=archiver_test --dest h=192.168.12.162,u=dba,p='123456',D=archiver_db,t=archiver_test --where '1=1' --progress 1000 --limit=10000 --txn-size=10000 --no-safe-auto-increment --statistics --purge
  • 不归档直接删除原表数据
pt-archiver --source h=192.168.12.161,u=dba,p='123456',D=martin,t=archiver_test --where '1=1' --progress 1000 --limit=10000 --txn-size=10000 --no-safe-auto-increment --statistics --purge
  • 按条件归档部分数据
pt-archiver --source h=192.168.12.161,u=dba,p='123456',D=martin,t=archiver_test --dest h=192.168.12.162,u=dba,p='123456',D=archiver_db,t=archiver_test --where 'age<30' --progress 1000 --limit=10000 --txn-size=10000 --no-safe-auto-increment --statistics --purge
  • 归档到文件
pt-archiver --source h=192.168.12.161,u=dba,p='123456',D=martin,t=archiver_test --where 'age<30' --progress 1000 --limit=10000 --txn-size=10000 --no-safe-auto-increment --statistics --purge --file=archiver.sql
# 指定文件格式 --output-format=csv
pt-archiver --source h=192.168.12.161,u=dba,p='123456',D=martin,t=archiver_test --where 'age<30' --progress 1000 --limit=10000 --txn-size=10000 --no-safe-auto-increment --statistics --purge --file=archiver.csv --output-format=csv
  • 通过ChatGPT编写自动化归档脚本

设计一张MySQL日志表,包括日志信息,记录时间和主键
通过pt-archiver,帮忙写一个martin库的logs表归档的shell脚本,这个实例的IP是192.168.12.161,超过30天的数据归档到实例192.168.12.163中的archiver_db中的logs表中。两个数据库的连接用户都是dba,密码是Id81Gdac_a

其它一些PT工具

信息汇总工具pt-mysql-summary

  • 用法
pt-mysql-summary --user=dba --password='123456' --host=192.168.12.161

参数分析工具pt-variable-advisor

  • 用法
pt-variable-advisor h=192.168.12.161,u=dba,p=123456

复制拓扑发现工具pt-slave-find

pt-slave-find h=192.168.12.161,u=dba,p=123456
  • 只显示复制拓扑
pt-slave-find h=192.168.12.161,u=dba,p=123456 --report-format=hostname

参数差异对比工具pt-config-diff

  • 对比两个实例的配置文件
pt-config-diff h=192.168.12.161,u=dba,p=123456 h=192.168.12.162,u=dba,p=123456
  • 对比mysql服务中的配置和配置文件
pt-config-diff /data/mysql/conf/my.cnf h=192.168.12.161,u=dba,p=123456
  • 对比两个配置文件
pt-config-diff /data/mysql/conf/my.cnf /data/my.cnf

权限查看工具pt-show-grants

pt-show-grants h=192.168.12.161,u=dba,p=123456
  • 增加drop user命令
pt-show-grants h=192.168.12.161,u=dba,p=123456 --drop

查找重复索引工具pt-duplicate-key-checker

pt-duplicate-key-checker h=192.168.12.161,u=dba,p=123456

查看磁盘IO状态工具pt-diskstats

pt-diskstats
  • 监控某块磁盘的IO
pt-diskstats --device sda
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容