MySQL Shell 生产实战:用 mysqlsh 解决真实运维问题

摘要

0. 和「使用手册」怎么分工

文档 内容
MySQL Shell(mysqlsh)使用手册:常用功能速查 安装、连接、模式、\ 命令、util 语法速查
本文 生产问题 → 选哪组能力 → 关键选项与注意点

下文命令默认已能连上目标实例;远程请用 Classic(mysql:// / :3306),util.* 必须加 --js 或先 \js

1. 大版本升级前的体检闭环

问题: 5.7 / 8.0 → 8.4 前,手工扫不兼容项容易漏;希望发布流水线里有一道自动门禁。

做法: util.checkForServerUpgrade() 产出文本或 JSON → 脚本判断是否含 Error → 修复后重跑,直到干净再切包。

1
2
3
4
5
6
7
8
# 门禁:指定目标版本 + 读 my.cnf(部分检查依赖配置文件)
mysqlsh user@host:3306 --js -e '
util.checkForServerUpgrade(null, {
targetVersion: "8.4.0",
configPath: "/etc/my.cnf",
outputFormat: "JSON"
})
' > /tmp/upgrade_check.json

生产注意:

  • 账号至少 PROCESS + SELECT;检查的是当前数据与配置,改完库结构后要再跑一遍。

  • JSON 适合 CI;人工排障用默认 TEXT 更直观。

  • 详细条目解读与升级步骤见 MySql--从Mysql5.7升级到Mysql8,本文不重复。

2. 跨机逻辑迁移(并行 dump / load)

问题: 换机、迁机房、从自建到另一套 MySQL;mysqldump 单线程、大库窗口长,且恢复时不好断点续跑。

做法: 源库 dumpSchemas / dumpInstance → 文件或对象存储 → 目标库 loadDump

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# --- 源库:只迁业务库,排除垃圾库,多线程 + 进度 ---
mysqlsh user@src:3306 --js -e '
util.dumpSchemas(["appdb", "reportdb"], "/backup/mig_20260921", {
threads: 8,
showProgress: true,
consistent: true
})
'

# 或整实例,但排除指定库
mysqlsh user@src:3306 --js -e '
util.dumpInstance("/backup/full_20260921", {
threads: 8,
excludeSchemas: ["tmp", "test", "bak_old"],
showProgress: true
})
'

# --- 目标库:打开 local_infile,带 progressFile 便于中断后续传 ---
mysqlsh user@dst:3306 --sql -e "SET GLOBAL local_infile=1;"
mysqlsh user@dst:3306 --js -e '
util.loadDump("/backup/mig_20260921", {
threads: 8,
showProgress: true,
progressFile: "/tmp/load_mig.json"
})
'

正式环境常用组合:

目标 选项思路
先看会迁什么、有无兼容问题 dryRun: true(迁云时再加 ocimds: true
缩短停机:先结构后数据 一次 ddlOnly,业务窗口再 dataOnly / 全量 load
边导边灌 load 侧设 waitDumpTimeout(秒),dump 未完成也可开始 load
只要表不要账号 注意 users/grants 相关 include/exclude(按版本选项名查阅手册)

注意:一致性对 InnoDB 有保证;目录必须为空;权限不足会导致缺锁或无 binlog 位点。传统 mysqldump 流程对比见 MySql--导入与导出

3. 全量备份里的「定点恢复」

问题: 误删一张表 / 一个库,不想整实例回档。

做法 A: 日常就按表 dump,恢复更快。

1
2
3
4
5
6
mysqlsh user@src:3306 --js -e '
util.dumpTables("appdb", ["orders", "order_items"], "/backup/tables_orders", {
threads: 4
})
'
# 目标库 loadDump 该目录即可

做法 B: 已有实例级 dump,恢复时用 load 的过滤能力(按你所用 Shell 版本支持的 includeSchemas / includeTables 等)只加载需要的对象;或从备份目录只取对应表的 DDL/TSV 再 importTable(改数据时更灵活,步骤更碎)。

生产建议:对核心表单独保留「表级定期 dump」,比「出了事再从全量里抠」更稳。

4. 超大 CSV/TSV 回灌(ETL)

问题: 数仓/对方系统丢来几十 GB 文本,单线程 LOAD DATA 或应用 insert 太慢。

做法: Classic 连接 + local_infile=ON + util.importTable() 多线程切块。

1
2
3
4
5
mysqlsh mysql://user@host:3306 --sql -e "SET GLOBAL local_infile=1;"

mysqlsh mysql://user@host:3306 -- util import-table /data/events.csv \
--schema=appdb --table=events \
--dialect=csv --threads=8 --bytesPerChunk=64M

注意:

  • 必须 Classic,X Protocol 不行。

  • 字段分隔、换行、是否有表头要与文件一致;压缩包(.gz / .zst)可直接喂,但单文件压缩时并行度受限。

  • ddlOnly/CREATE TABLE 再导入;索引很多时可考虑先少索引、导完再建(需自己评估写入窗口)。

5. InnoDB Cluster:用 AdminAPI 管高可用

问题: 手写 Group Replication 参数易错;加节点、切主、全挂恢复需要标准动作。

做法: dba.* / cluster.* 管生命周期,Router 管流量。完整搭建与演练见 MySQL 8.4 InnoDB Cluster 的构建方法

生产里 Shell 侧高频动作示例:

1
mysqlsh icadmin@node1:3306 --js
1
2
3
4
5
var cluster = dba.getCluster()
cluster.status()
cluster.addInstance('icadmin@node3:3306')
cluster.setPrimaryInstance('icadmin@node2:3306')
// 全挂后的重启要走 rebootClusterFromCompleteOutage,不要凭感觉比 GTID

这是 mysql 客户端替代不了的能力;手册只作入口,细节以 Cluster 专文为准。

6. CI / cron:命令行 API 集成

问题: 备份、升级检查、巡检要进流水线,不能依赖人工进 REPL。

做法: mysqlsh [连接] -- <对象> <kebab-case 方法> ...

1
2
3
4
5
6
7
8
# 每天逻辑备份(示例:挂到 cron,注意凭证用 login-path / 环境注入,勿写死在命令行)
mysqlsh user@host:3306 -- util dump-schemas appdb /backup/appdb_$(date +%F) --threads=4

# 发布前升级门禁
mysqlsh user@host:3306 -- util check-for-server-upgrade --targetVersion=8.4.0

# 看 Shell 状态
mysqlsh -- shell status

适合 Ansible ad-hoc、GitLab CI job、备份主机定时任务。返回对象再链式调用的 API(如部分 getCluster() 后续操作)仍更适合脚本文件 + --js --file

7. 故障取证:一键打包诊断

问题: 主从延迟、打满、疑难杂症,需要把实例状态打包给同事或厂商,避免来回要 SHOW ENGINE / 状态表。

这类能力挂在 util.debug 下(调试/诊断工具集):

1
mysqlsh root@host:3306 --js -e 'util.debug.collectDiagnostics("/tmp/mysql_diag_$(hostname).zip")'
1
2
3
// 高负载采样、慢查询相关(选项见官方 Diagnostics 文档)
util.debug.collectHighLoadDiagnostics("/tmp/highload.zip")
util.debug.collectSlowQueryDiagnostics("/tmp/slow.zip")

文档:collectDiagnostics。注意包内可能含 schema/语句信息,外传前做脱敏与权限控制;远程实例通常只能采到 MySQL 侧信息,本机 host 信息需 Shell 跑在目标机上。

8. 环境间拷贝(测试库刷新)

问题: 定期把生产某几个库刷到预发;不想先落盘再 scp(或磁盘紧)。

做法: util.copySchemas / copyTables / copyInstance(需能同时访问源与目标;注意敏感数据与账号权限)。

1
2
3
4
5
// 示意:连接在「源」全局会话时,把库拷到另一实例(具体参数以当前版本 API 为准)
util.copySchemas(["appdb"], "user@staging:3306", {
threads: 4,
// 常配合用户/权限、一致性等相关选项;生产务必先 dryRun / 小库验证
})

合规要求高时,优先「脱敏流水线 + dump/load」,而不是直连生产拷到测试。

9. 迁云 / HeatWave 前的兼容改造

问题: 上云或 HeatWave 时 DEFINER、引擎、主键等不符合目标环境。

做法: dump 时 ocimds: true + dryRun 先出问题清单,再加 compatibility 数组做自动改写(如 strip_definers 等),确认后再正式 dump/load。

1
2
3
4
5
util.dumpInstance("/backup/ocimds_dry", {
dryRun: true,
ocimds: true
})
// 按报告选择 compatibility 后再去掉 dryRun 正式导出

选项随 Shell 版本增加,迁云前用最新 mysqlsh 并对着官方 Utilities 文档核对。

10. 推荐落地组合(可直接抄进 runbook)

A. 「周五发布」最小集

  1. CI:check-for-server-upgrade(有大版本变更时)

  2. 发布前:业务库 dumpSchemas 到备份机

  3. 发布后:应用健康检查;失败则用昨晚 dump loadDump 到备用实例切流量(按你司 SOP)

B. 「换机迁移」最小集

  1. 源:dumpSchemasconsistent: true,线程数按磁盘/CPU 压测)

  2. 目标:建好账号与 local_infileloadDump + progressFile

  3. 追增量:窗口内停写或用 binlog/业务双写(Shell 也有 binlog dump/load,链路更重,需单独设计)

  4. 校验:行数、校验和、关键业务抽检

C. 「误删表」最小集

  1. 日常:核心表 dumpTables 保留 N 天

  2. 恢复:load 到临时库 → 校验 → RENAME / 应用切换

11. 生产使用底线

  • 凭证:不要用 user:password@host;用交互、Secret Store 或 login-path(见 MySQL Shell(mysqlsh)使用手册:常用功能速查 §3.4)。

  • --no-defaults 排除本机 ~/.my.cnf 串密到错误实例。

  • dump 目录权限与磁盘空间按压缩后体积预留余量;先小库压测线程数。

  • loadDump / importTable 会显著打满 IO 与连接数,避开业务高峰或走备库导出。

  • AdminAPI 操作前确认连的是预期成员;生产切主带 runningTransactionsTimeout 等参数,见 Cluster 专文。

参考