MySQL 常用排障与救火速查 (Runbook)

🚨 使用指南: 这是一份专为生产环境数据库宕机、卡顿、爆满设计的救火急诊室指南。越致命的状况对应的代码越靠前,日常业务代码被折叠至附录。在此页面所抄写的每一行指令,都应该怀揣对生产环境的敬畏。

01. 致命故障阻断:连接爆满与死锁

定位卡死的源头查询

当业务发生大面积连接超时(Too many connections),必须立即揪出源头。

1
2
3
4
5
# 查看全盘正在执行的所有线程与查询。重点盯住 `Time` 耗时超长的行,和 `State`  Locked 的进程。
show full processlist;

# 选定特定祸首(譬如 Id  1024的查询),手动狙杀以释放表锁:
kill 1024;

批量猎杀僵尸查询(雪崩级自救)

当数据库瞬间被几十上百个卡死的查询打满,一个个 COPY ID 根本来不及,你可以利用下面语句跑出批量 KILL 脚本:

1
2
3
4
# 找出所有运行超过 30 秒并在指定库下执行的坏死语句,让引擎自动吐出批量 KILL 指令。
select concat('KILL ',id,';') from information_schema.processlist 
where db='你的库名' and time > 30 and command = 'Query';
# 将上一步产出的多行 KILL 代码复制,并一键黏贴至控制台批量斩杀!

定位深层死锁与哪张库表堵塞

1
2
3
4
5
# 查询有哪张表正在被死锁占用处于写入阻塞中 (In_use 大于 0 代表被锁)
show open tables where In_use > 0;

# 查询底层 InnoDB 引擎的运转全貌与事务挂起细节(硬核排查指令)
show engine innodb status;

02. 特权拉起与账号盲切抢救

免密强拉服务(忘 Root 密码 / 权鉴紊乱自救)

如果因为乱改权限导致数据库完全锁死谁也连不进去,连 Root 密码都被遗忘:

1
2
3
4
5
6
# 1. 在 Linux 服务台停掉 MySQL 服务
systemctl stop mysqld
# 2. 利用跳过授权表模式强行拉起服务,直接跨过登陆鉴权网
mysqld_safe --skip-grant-tables &
# 3. 此时可以直接由于空密码登入 MySQL 开始重置你的正常帐户和权限了!
mysql -u root

阻断异常暴露:给内网降级配置临时入口

1
2
3
4
# 紧急创建一个只能在专门客户端网段 (%) 连入的排障专用号,锁定至单一业务库避免祸及池鱼
create user 'sos_user'@'%' identified by 'strong_password';
grant all privileges on your_db_name.* to 'sos_user'@'%';
flush privileges;

03. 性能深潜与大口径清洗

执行计划:质检索引缺失导致的隐性卡顿

业务不会宕机,就是单纯拖慢了 CPU 和 I/O,通常是索引缺失。

1
2
# 在极慢的日志查询前加上 EXPLAIN,重点看 `type` 字段,如果是 'ALL' 即引发了最坏的全表扫描。
explain select * from user_logs where created_at > '2022-10-01';

脏数据防炸阻断(防爬虫注入崩溃)

1
2
3
# 上游送来的数据主键如果冲突了不报错终止写入,转为安全的 Update 覆盖策略
insert into my_table (id, name, count) values (1, 'apple', 1) 
on duplicate key update count = count + 1;

大面数据纠偏清洗 (利用高频的 JOIN UPDATE)

1
2
3
4
5
# 利用 B 表(准数据字典)的最新数据去强制刷新修复 A 表损坏的数据
update table_a a 
inner join table_b b on a.id = b.a_id 
set a.status = b.status 
where a.status != b.status;

04. 灾后数据导出抢救

当磁盘快要报警红线:舍车保帅库抛离算法

如果一个几百 G 的历史归档库马上要吃光操作系统的 IO 容量,你需要强行抽出核心表保命。

1
2
3
4
5
# `--ignore-table` 极度实用:导出时强行剔除无用的海量流水线日志大表,秒速把最核心库备份抽离换台机器
mysqldump -uroot -p"Password" --databases itoa126 --ignore-table=itoa126.scr_big_log_table > /app/dump_core.sql

# 也可以借助 Linux 管道过滤,一通导出来只包含你需要的关键业务分库
mysql -e "show databases;" -uroot -p"Pass" | grep -Ev "Database|test|information_schema" | xargs mysqldump -uroot -p"Pass" --databases > /app/dump_clean.sql

百万数据导出为 CSV 将压力脱手

1
2
3
4
#  MySQL 引擎的 I/O 底层直写文件,防止导出几百万行数据把你的运维客户端直接卡死爆炸
select from_unixtime(left(event_time,10)),origin_id from tb_event 
where merge_key=1 order by event_time 
into outfile '/tmp/tb_event_20221017.csv' fields terminated by ',';

附录:日常业务打磨工具箱

核级删除:极速清空表

1
2
# 相比 Delete 性能极速,且不记入日志,不可回滚,自增 ID 会重置!
truncate table table_name;

UNIX 时间戳转换

1
2
3
select unix_timestamp('2022-03-21 14:28:30') from tb_event;
# 时间戳转回可用日期版
select from_unixtime(1666060280, '%Y-%m-%d %H:%i:%S') from tb_event;