这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
模块:MySQL
使用 Pigsty 部署原生 MySQL 8.4 LTS 单机或三节点 InnoDB Cluster,附带 TLS、每日备份与完整监控。
MySQL 是世界上最流行的开源关系型数据库之一。Pigsty 的 MYSQL 模块在纳管节点上部署固定的原生 MySQL 8.4 LTS 平台:单机实例,或基于 Group Replication 的三节点单主 InnoDB Cluster,并统一管理 TLS、备份、监控与生命周期。
当前状态:Pilot 试点模块
MYSQL 是补充性的试点模块,定位是「简单、廉价、够用」的 MySQL 集群,不追求与 PGSQL 模块同级的完备性。
核心能力(部署收敛、高可用切换、每日备份、监控告警)已经过系统性测试;
完全停机恢复、物理备份恢复等破坏性流程刻意保留为手工运维操作,参见日常管理中的操作手册。
模块能力
MYSQL 模块当前提供:
- 固定的原生 MySQL 8.4 LTS 平台:Server、Client、Shell、Router、XtraBackup 版本一致,开箱即用
- 两种拓扑:单机实例,或三节点单主 InnoDB Cluster(MySQL Shell AdminAPI 创建与收敛)
- 每个 HA 成员本机部署 MySQL Router,提供拓扑感知的读写(
6446)与只读(6447)入口 - 全链路强制 TLS:复用 Pigsty 共享 CA 签发节点叶证书,拒绝非加密连接
- 声明式业务对象:
mysql_databases 与 mysql_users 增量收敛,不隐式删除数据 mysql_parameters 参数覆盖:调整关键参数(如 max_connections),配置变更自动编排滚动重启- 每日全量物理备份:XtraBackup 备份并完成整备(prepare),带保留策略、并发锁与原子提交
- 完整可观测性:mysqld_exporter 指标、68 条预置衍生规则、27 条告警规则、5 个 Grafana Dashboard、错误日志入 VictoriaLogs
- 默认启用
sql_require_primary_key:拦截无主键表,保护 MGR 复制与灾难恢复 - 收敛式运维:成员掉线、AdminAPI 状态漂移等场景重跑
mysql.yml 即可自愈;危险操作有安全护栏
模块架构
MYSQL 模块依赖 NODE 完成节点纳管、软件仓库与共享 CA,依赖 INFRA 提供 VictoriaMetrics、VictoriaLogs、Grafana 与 Alertmanager。不依赖 ETCD 与 PGSQL。
flowchart LR
admin["Pigsty 管理节点"] -->|"mysql.yml"| mysqld["mysqld ×3 / MGR 单主<br>3306 · TLS"]
client["业务客户端"] -->|"RW 6446 / RO 6447"| router["MySQL Router<br>(每个 HA 成员)"]
router --> mysqld
mysqld --> backup["XtraBackup 每日全备<br>(仅当前主库)"]
mysqld --> exporter["mysqld_exporter :9104"]
mysqld --> journal["错误日志 → Journald"]
exporter --> vm["VictoriaMetrics"]
journal --> vector["Vector"] --> vl["VictoriaLogs"]
vm --> grafana["Grafana"]
vl --> grafana
vm --> alertmanager["Alertmanager"]
style mysqld fill:#4479A1,stroke:#33618a,color:#fff
style router fill:#70C1B3,stroke:#4f968b,color:#fff
style vm fill:#E66B7A,stroke:#b84e5c,color:#fff
style vl fill:#C98367,stroke:#9e634e,color:#fff三节点模式下 mysql_seq=1 只是首次引导协调者:运行时 PRIMARY 由选举产生,重跑剧本不会把主库强制切回 1 号节点。
组件与端口
| 组件 | 用途 | 固定端点 |
|---|
mysqld | 单机服务或 MGR 成员 | Classic 3306、X Protocol 33060 |
| Group Replication | 三节点复制与共识(XCOM) | 33061 |
| MySQL Router | HA 拓扑感知入口,每个成员均部署 | RW 6446、RO 6447 |
| MySQL Shell | AdminAPI 生命周期管理 | 本机控制面 |
| XtraBackup | 每日全量物理备份 | 本地备份仓库 |
mysqld_exporter | MySQL 与 MGR 指标 | 9104 |
角色创建并管理三个平台身份:
dbuser_cluster@'%':要求 TLS 的 AdminAPI 与 Router 引导身份(仅 HA 集群创建);dbuser_monitor@'127.0.0.1':最小权限 Exporter 身份;dbuser_backup@'localhost':本地 XtraBackup 身份。
平台支持
原生软件包平台门禁为:
| 架构 | 支持的系统 |
|---|
x86_64 | EL 8/9/10、Debian 12/13、Ubuntu 22/24 |
aarch64 | EL 9/10 |
Debian/Ubuntu ARM64 会被预检拒绝:Oracle APT 仓库的 MySQL 8.4 组件没有 arm64 载荷。ARM 环境请使用 EL 9/10(如 Rocky Linux)。
能力边界
MYSQL 是固定平台,不是通用 MySQL 安装器。以下事项有意不做,使用前请确认可以接受:
- 拓扑固定为 1 或 3 节点:不支持 1→3 原地升级、3→5 扩容或长期两节点拓扑;容量升级通过逻辑迁移完成,硬件更换通过同地址替换完成
- 版本、端口、目录、字符集固定:不暴露相应参数;内存参数按节点规格自动推导,可用
mysql_parameters 覆盖关键参数 - 备份为每日本地全量:无增量链、无 Binlog 连续归档、无 PITR;物理恢复是手工流程(附操作手册)
- 完全停机恢复保留为手工操作:防止自动化误判造成脑裂,剧本失败信息会给出恢复指引
- 无 VIP / DNS / HAProxy 接入层:客户端通过任一成员的 Router 端口或多地址 DSN 接入
文档目录
| 文档 | 说明 |
|---|
| 集群配置 | 拓扑规划、身份参数、业务库表用户、参数覆盖与备份配置 |
| 参数参考 | 11 项公开参数与固定平台约定 |
| 日常管理 | 状态检查、客户端接入、配置变更、故障处理与三份恢复手册 |
| 预置剧本 | mysql.yml 与 mysql-rm.yml 的用法、标签与安全护栏 |
| 监控告警 | Dashboard、衍生规则、告警规则与日志查询 |
| 指标定义 | 标签模型与衍生指标字典 |
| 常见问题 | 平台限制、主键要求、恢复与排障 |
快速开始
在清单中声明集群(完整模板见 conf/demo/mysql.yml):
all:
children:
my-test:
hosts:
10.10.10.11: { mysql_seq: 1 }
10.10.10.12: { mysql_seq: 2 }
10.10.10.13: { mysql_seq: 3 }
vars:
mysql_cluster: my-test
mysql_databases: [ { name: app } ]
mysql_users: [ { name: app, password: DBUser.App, priv: { 'app.*': 'ALL PRIVILEGES' } } ]
vars:
node_repo_modules: node,infra,mysql # 软件仓库需包含 mysql 模块
mysql_root_password: MySQL.Root # 生产环境必须修改示例密码
mysql_monitor_password: MySQL.Monitor
mysql_cluster_password: MySQL.Cluster
完成 NODE 纳管后执行部署:
./node.yml -l my-test # 节点纳管:仓库、共享 CA、监控代理
./mysql.yml -l my-test --check # 预检完整三节点集群
./mysql.yml -l my-test # 真实部署,三节点约 2 分钟
mysql -h 10.10.10.11 -P 6446 -u app -pDBUser.App \
--ssl-mode=VERIFY_CA --ssl-ca=/etc/pki/ca.crt app # 通过 Router 读写入口接入
部署后访问 Grafana 的 MySQL Overview Dashboard 查看集群状态。
1 - 集群配置
规划 MySQL 拓扑与身份,声明业务数据库、用户、参数覆盖与备份策略。
MYSQL 模块通过清单(Inventory)声明集群,mysql.yml 将现场收敛到声明状态。本页介绍拓扑规划与全部配置项的写法;参数细节见参数参考。
部署前检查
- 目标节点已完成
NODE 纳管,共享 CA 已安装到 /etc/pki/ca.crt(由 node_ca 负责,MySQL 角色只签发叶证书); - 软件仓库包含
mysql 模块:node_repo_modules: node,infra,mysql,或本地仓库已缓存 repo_extra_packages: [mysql]; - 平台在支持矩阵内:
x86_64 的 EL 8/9/10、Debian 12/13、Ubuntu 22/24,或 aarch64 的 EL 9/10; - 三个平台密码(
mysql_root_password、mysql_monitor_password、mysql_cluster_password)已改为生产值——预检会拒绝 CHANGE_ME 开头的占位密码。
身份参数
每套集群由清单分组声明,两个身份参数必填:
| 参数 | 层级 | 说明 |
|---|
mysql_cluster | 集群 | 集群名,必须与清单分组名一致(成员须位于同名分组);也是备份目录与监控 cls 标签 |
mysql_seq | 实例 | 单机为 1;HA 为连续的 1..3,同时作为 server_id |
拓扑由成员数量决定:1 个成员是单机,3 个成员是 InnoDB Cluster,其他数量会被预检拒绝。mysql_seq=1 只是首次引导协调者,不代表运行时主库。
实例名为 {{ mysql_cluster }}-{{ mysql_seq }}(如 my-test-1)。清单中的主机地址(IP 或可解析主机名)就是 MySQL 与 MGR 的通告地址,部署后不可通过普通重跑变更。
单机实例
最小可用的单机声明:
my-meta:
hosts:
10.10.10.10: { mysql_seq: 1 }
vars:
mysql_cluster: my-meta
单机没有 Router(6446/6447 不存在),客户端直连 3306。备份、监控、TLS 与 HA 模式完全一致。
三节点 InnoDB Cluster
my-test:
hosts:
10.10.10.11: { mysql_seq: 1 }
10.10.10.12: { mysql_seq: 2 }
10.10.10.13: { mysql_seq: 3 }
vars:
mysql_cluster: my-test
mysql_databases:
- { name: app }
mysql_users:
- name: app
host: '%'
password: DBUser.App
connlimit: 20
priv: { 'app.*': 'ALL PRIVILEGES' }
部署后形成单主 MGR:一个 PRIMARY 可写,两个 SECONDARY 只读,容忍一台故障。每个成员运行 Router,从任一成员的 6446 都能到达当前主库。
每次操作都要选择完整集群
所有 mysql.yml 操作必须用 -l 选中该集群的全部成员(或不加 -l 收敛所有 MySQL 集群)。部分成员选择会在预检阶段被拒绝,这是防止拓扑分歧的刻意设计。
业务数据库
mysql_databases 是增量声明的数据库列表:
mysql_databases:
- { name: app } # 默认 utf8mb4 / utf8mb4_0900_ai_ci
- { name: app2, encoding: utf8mb4, collate: utf8mb4_general_ci }
| 字段 | 默认值 | 说明 |
|---|
name | 必填 | 库名,[A-Za-z0-9_$-],不能使用系统库名 |
encoding | utf8mb4 | 字符集 |
collate | utf8mb4_0900_ai_ci | 排序规则 |
encrypt | false | 库级 DEFAULT ENCRYPTION;需自行配置 InnoDB Keyring 组件(平台未预置,未配置时建表会失败) |
声明是增量收敛:重跑会创建缺失的库,但从列表删除条目不会 DROP 数据库。删除数据属于手工运维操作。
所有表都必须有主键
平台默认启用 sql_require_primary_key=ON:创建无主键表会报 ERROR 3750。这不是刁难——无主键表在 MGR 下只读不可写,还会在灾难恢复时阻塞 AdminAPI 重建集群。请为所有表定义主键(或使用不可见列主键);确有特殊需要时可通过 mysql_parameters 关闭。
业务用户
mysql_users 是增量声明的用户与授权列表:
mysql_users:
- name: app # 用户名
host: '%' # 授权来源,默认 '%'
password: DBUser.App # 必填,支持特殊字符
connlimit: 20 # MAX_USER_CONNECTIONS,0 为不限
priv: # 授权映射:'库.表' -> 权限列表
'app.*': 'ALL PRIVILEGES'
'app2.*': 'SELECT, INSERT, UPDATE, DELETE'
授权范围写作 '库.表',两侧都可以用 * 通配(如 '*.*'、'app.*');权限值为逗号分隔的权限名。预检会校验用户名、host、权限范围与权限词的合法性,拒绝畸形声明。
行为约定:
- 用户不存在则创建,存在则按声明更新密码与连接数上限;
priv 中的授权会被执行(GRANT),但移除映射不会自动 REVOKE;- 不能声明
root、dbuser_monitor、dbuser_cluster、dbuser_backup 这些平台身份; - 服务端强制 TLS:客户端默认的
PREFERRED 模式会自动协商加密,明文连接(DISABLED)会被拒绝;建议显式使用 VERIFY_CA 校验证书。
参数覆盖
mysql_parameters 用于覆盖 [mysqld] 配置,追加渲染在托管配置末尾(同名参数后写生效):
my-test:
vars:
mysql_cluster: my-test
mysql_parameters:
max_connections: 500
long_query_time: 2
innodb_print_all_deadlocks: true # 布尔渲染为 ON/OFF
规则与安全边界:
- 键名须为普通选项名(字母开头,可含
._-),值必须是单行标量; - 渲染后的配置仍会经过
mysqld --validate-config 校验,非法参数在部署阶段即失败,不会影响运行中的服务; - 平台保留参数不可覆盖:身份(
server_id、datadir、port、socket、bind_address、report_host 等)、复制(gtid_mode、log_bin、group_replication_*)与 TLS(require_secure_transport、ssl_*)由角色统一管理,声明即拒绝; - 参数变更会触发编排式滚动重启:从库先行、主库殿后。
内存基线无需配置:缓冲池为节点内存的 25%(下限 256MB),Redo 容量为缓冲池一半(128MB–4GB),复制并行度按 CPU 推导。需要精确控制时用 mysql_parameters 覆盖 innodb_buffer_pool_size 等参数即可。
备份配置
mysql_backup_enabled: true # 默认开启每日备份
mysql_backup_repo:
local:
path: /data/backups/mysql # 本地备份根目录
retention: 7 # 保留最近 7 份全量
备份契约(详见日常管理):
- 每日一次 XtraBackup 全量物理备份,备份后立即 prepare,产出可直接恢复的目录;
- 单机在本机备份;HA 由每个成员的定时器各自触发,但只有当前 PRIMARY 真正执行,其余成员自动跳过;
- 目录布局
<path>/<cluster>/<UTC 时间戳>/,latest 符号链接原子指向最新一份,按 retention 剪枝; - 没有增量链、Binlog 归档与 PITR;单机场景的恢复点就是最近一次备份。
备份位置跟随主库
HA 集群发生主从切换后,新备份会落在新主库的本地磁盘上。恢复前请在所有成员上检查 latest 指向的时间戳,取最新的一份。异地容灾请自行同步备份目录(如 rclone/rsync 定时任务)。
平台凭据
mysql_root_password: MySQL.Root # 本地 root(root@localhost,仅本机套接字)
mysql_monitor_password: MySQL.Monitor # Exporter 监控身份
mysql_cluster_password: MySQL.Cluster # AdminAPI / Router / 备份身份
凭据的生命周期约定:
- 密码不能包含换行,不能保留
CHANGE_ME 前缀,预检强制校验; - HA 集群的
mysql_cluster_password 不能通过普通重跑轮换:它已写入集群 Metadata 与 Router 密钥环,隐式轮换会被预检拒绝(单机实例无此绑定,改清单重跑即生效); mysql_root_password 同样不能隐式重置:现场 root 密码与声明不一致时任务会明确报错,避免误配置静默改密。
凭据材料落盘在 /etc/mysql/pigsty/(root 属主:目录 0700、文件 0600),包括 root 与集群身份的客户端配置文件,可供本机运维直接使用:
mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf # 本机 root 会话
mysql --defaults-extra-file=/etc/mysql/pigsty/cluster.cnf # 经本机 Router 的集群会话(仅 HA 成员)
完整示例
单机加三节点的完整参考(对应四节点沙箱):
all:
children:
infra:
hosts:
10.10.10.10: { infra_seq: 1 }
my-meta:
hosts:
10.10.10.10: { mysql_seq: 1 }
vars: { mysql_cluster: my-meta, node_cluster: my-meta }
my-test:
hosts:
10.10.10.11: { mysql_seq: 1 }
10.10.10.12: { mysql_seq: 2 }
10.10.10.13: { mysql_seq: 3 }
vars:
mysql_cluster: my-test
node_cluster: my-test
mysql_databases:
- { name: app }
mysql_users:
- { name: app, password: DBUser.App, priv: { 'app.*': 'ALL PRIVILEGES' } }
mysql_parameters:
max_connections: 500
vars:
version: v4.5.0
admin_ip: 10.10.10.10
region: china # 中国大陆使用 USTC/腾讯镜像
node_repo_modules: node,infra,mysql
node_tune: oltp
mysql_root_password: MySQL.Root
mysql_monitor_password: MySQL.Monitor
mysql_cluster_password: MySQL.Cluster
完整模板见 conf/demo/mysql.yml。注意 conf/mysql.yml 是 OpenHalo(PostgreSQL 内核的 MySQL 兼容方案)模板,与本模块无关。
2 - 参数参考
MYSQL 模块 11 项公开参数与固定平台约定。
MYSQL 角色刻意只公开 11 项参数。软件版本、端口、目录、字符集、TLS 路径与定时器表达式由角色统一固定,内存基线按节点规格推导;需要调整服务器行为时使用 mysql_parameters。
参数概览
旧版页面曾出现的 mysql_role、mysql_services、mysql_packages、mysql_data、mysql_port、mysql_replication_*、mysql_*_username 等变量已不属于公开接口,请勿使用。
身份参数
mysql_cluster
必填的集群身份,必须与清单分组名一致(预检要求成员位于同名分组)。字母、数字或下划线开头,可含 ._-,最长 63 字符:
用于生成实例名(my-test-1)、MGR Group UUID(由集群名确定性推导)、备份目录(<repo>/my-test/)与监控标签 cls。
mysql_seq
必填的实例序号。单机为 1;三节点必须是连续的 1、2、3,并直接作为 server_id:
10.10.10.11: { mysql_seq: 1 }
mysql_seq=1 仅表示首次引导时的协调者;运行时主库由 MGR 选举决定,重跑剧本不会迁回主库。
凭据参数
mysql_root_password
本地 root@'localhost' 密码,仅限本机使用(套接字或回环地址)。不能包含换行,不能保留 CHANGE_ME 前缀:
mysql_root_password: MySQL.Root
首次启动时设置;此后如果现场密码与声明不一致,任务会拒绝隐式重置并明确报错——修改 root 密码需要先手工 ALTER USER 再同步清单。
mysql_monitor_password
dbuser_monitor@'127.0.0.1' 密码,供 mysqld_exporter 使用,仅限本机回环地址、最多 3 连接、只读权限:
mysql_monitor_password: MySQL.Monitor
mysql_cluster_password
dbuser_cluster@'%'(要求 TLS)与 dbuser_backup@'localhost' 共用的平台密码,用于 AdminAPI 集群管理、Router 引导与 XtraBackup:
mysql_cluster_password: MySQL.Cluster
HA 集群中该密码写入集群 Metadata 与 Router 密钥环,不能通过普通重跑轮换:现场值与声明不一致时预检直接拒绝。单机实例无此绑定,改清单重跑即生效。
业务对象
mysql_databases
增量收敛的业务数据库列表,字段 name / encoding / collate / encrypt:
mysql_databases:
- { name: app }
- { name: app2, encoding: utf8mb4, collate: utf8mb4_general_ci, encrypt: false }
只创建与更新,不会因移除条目而删除数据库。写法与校验规则见集群配置。
mysql_users
增量收敛的业务用户列表,字段 name / host / password / connlimit / priv:
mysql_users:
- name: app
host: '%'
password: DBUser.App
connlimit: 20
priv: { 'app.*': 'ALL PRIVILEGES' }
授权只增不减(移除映射不会 REVOKE);平台身份(root、monitor、cluster、backup)不可声明。写法与校验规则见集群配置。
mysql_parameters
[mysqld] 段参数覆盖字典,渲染在托管配置末尾,同名参数后写生效:
mysql_parameters:
max_connections: 500
long_query_time: 2
innodb_buffer_pool_size: 2G
innodb_print_all_deadlocks: true # true/false 渲染为 ON/OFF
约束与行为:
- 键名
[A-Za-z][A-Za-z0-9_.-]{0,63},值为单行标量;渲染后仍经 mysqld --validate-config 校验,写错参数在部署阶段失败而不影响运行中的实例; - 保留参数拒绝覆盖(
-/_ 写法同判):user、pid_file、server_id、datadir、socket、port、bind_address、mysqlx_bind_address、report_host、gtid_mode、enforce_gtid_consistency、log_bin、relay_log、plugin_load_add,以及 group_replication_* 与 TLS 相关(require_secure_transport、ssl_*)全族; - 变更后重跑
mysql.yml 触发编排式滚动重启(从库先行、主库殿后),HA 集群预期仅主库切换瞬间有秒级写中断; - 平台默认值中可覆盖的典型项:
sql_require_primary_key(默认 ON)、long_query_time(默认 1)、binlog_expire_logs_seconds(默认 7 天)、内存类参数。
会话级动态参数(AdminAPI 通过 SET PERSIST 管理的少数复制参数)以运行时为准;角色会在每次收敛时把 group_replication_group_seeds 钉回声明成员表,避免持久化漂移。
备份参数
mysql_backup_enabled
是否启用每日备份定时器(mysql-backup.timer,每日触发、随机延迟 30 分钟内):
mysql_backup_enabled: true
设为 false 停用定时器,但保留备份脚本与配置。注意:若备份目录从未创建过(备份从未启用),手工触发会因目录缺失直接退出。
mysql_backup_repo
本地备份仓库定义,当前只支持 local 一种方式:
mysql_backup_repo:
local:
path: /data/backups/mysql # 绝对路径,不能与数据目录重叠
retention: 7 # 保留最近 N 份已提交全量(1-9999)
目录布局与恢复流程见日常管理。
监控参数
mysql_exporter_enabled
是否启用 mysqld_exporter 与 VictoriaMetrics Target 注册:
mysql_exporter_enabled: true
设为 false 时停用 Exporter 服务,并将 /infra/targets/mysql/<实例>.yml 收敛为空列表(不删除文件;文件只由 mysql-rm.yml 删除)。
固定平台约定
以下值由角色固定或推导,不是清单参数,列出供运维参考:
| 项目 | 值 |
|---|
| 软件版本 | MySQL Server/Client/Shell/Router 8.4 LTS、Percona XtraBackup 8.4 |
| 端口 | 3306(Classic)、33060(X Protocol,单机仅回环)、33061(MGR)、6446/6447(Router RW/RO)、9104(Exporter) |
| 数据目录 | /var/lib/mysql(Binlog 于 binlog/ 子目录,7 天过期) |
| 配置文件 | EL:/etc/my.cnf.d/pigsty.cnf;Debian/Ubuntu:/etc/mysql/mysql.conf.d/pigsty.cnf |
| 服务单元 | MySQL:EL 为 mysqld,Debian/Ubuntu 为 mysql;Router:mysqlrouter;Exporter:mysqld_exporter |
| 凭据与脚本 | /etc/mysql/pigsty/(root 属主:目录 0700、文件 0600) |
| 日志 | 错误日志 /var/log/mysql/error.log 并镜像到 Journald;慢查询 /var/log/mysql/slow.log(阈值 1s) |
| TLS | 强制加密(require_secure_transport=ON);CA /etc/pki/ca.crt,叶证书 /etc/mysql/pki/ |
| 字符集 | utf8mb4 / utf8mb4_0900_ai_ci |
| 内存基线 | 缓冲池 = max(节点内存 × 25%, 256MB);Redo = clamp(缓冲池 × 50%, 128MB, 4GB) |
| 复制 | GTID 强制、sql_require_primary_key=ON、MGR 单主、故障切换读一致性 BEFORE_ON_PRIMARY_FAILOVER |
| 数据目录标记 | .pigsty-mysql-initialized(属主校验)与 .pigsty-mysql-retired(退役防护) |
3 - 日常管理
MySQL 集群的状态检查、客户端接入、配置变更、故障处理,以及成员替换、物理恢复与完全停机恢复三份操作手册。
本页覆盖 MYSQL 模块的日常运维操作。总原则:声明状态改清单,收敛现场跑剧本——成员掉线、AdminAPI 状态漂移等多数异常,重跑一次 ./mysql.yml -l <集群> 即可自愈;只有三类破坏性场景(替换成员、恢复备份、完全停机恢复)需要按本页手册人工介入。
速查手册
| 操作 | 命令 |
|---|
| 部署 / 收敛集群 | ./mysql.yml -l <集群> |
| 预检(不改现场) | ./mysql.yml -l <集群> --check |
| 本机 root 会话 | mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf |
| 查看 MGR 拓扑 | SELECT MEMBER_HOST,MEMBER_STATE,MEMBER_ROLE FROM performance_schema.replication_group_members; |
| AdminAPI 状态 | mysqlsh 连接后 dba.getCluster().status() |
| 手工触发备份 | systemctl start mysql-backup(HA 上仅主库真正执行) |
| 退役一个从库 | ./mysql-rm.yml -l <IP> -e mysql_safeguard=false -e mysql_rm_confirm=<实例名> |
| 下线整个集群 | ./mysql-rm.yml -l <集群> -e mysql_safeguard=false -e mysql_rm_confirm=<集群名> |
状态检查
本页命令需以 root 在集群成员上执行(/etc/mysql/pigsty/ 下的客户端配置与密钥仅 root 可读)。示例以 EL 为准:Debian/Ubuntu 上 MySQL 服务单元名为 mysql 而非 mysqld。
在任意成员上确认服务与拓扑:
systemctl status mysqld mysqlrouter mysqld_exporter mysql-backup.timer
mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -e "
SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE, MEMBER_VERSION
FROM performance_schema.replication_group_members ORDER BY MEMBER_HOST;"
健康的三节点集群应显示 3 行 ONLINE,其中恰好 1 个 PRIMARY。需要 AdminAPI 视角时:
mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"127.0.0.1", port:3306,
"ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
print(dba.getCluster().status());'
集群级健康也可以直接看 Grafana MySQL Overview,或查询衍生指标 mysql:cls:health(2 健康 / 1 降级 / 0 危险)。
客户端接入
HA 集群通过任一成员的 Router 端口接入,Router 自动跟随主从切换:
# 读写入口(当前主库)
mysql -h <任一成员> -P 6446 -u app -pDBUser.App --ssl-mode=VERIFY_CA --ssl-ca=/etc/pki/ca.crt app
# 只读入口(从库轮询)
mysql -h <任一成员> -P 6447 -u app -pDBUser.App --ssl-mode=VERIFY_CA --ssl-ca=/etc/pki/ca.crt app
接入建议:
- 服务端强制 TLS,明文连接会被拒绝;普通客户端默认的
PREFERRED 模式即可自动协商加密,建议显式 VERIFY_CA(JDBC:sslMode=VERIFY_CA)并信任 Pigsty CA; - 模块不提供 VIP/DNS 接入层。为避免单一 Router 节点成为断点,应用侧建议配置多地址 DSN,例如 JDBC
jdbc:mysql://10.10.10.11:6446,10.10.10.12:6446,10.10.10.13:6446/app,或在应用侧负载均衡器中列出全部成员; - 单机集群没有 Router,直连
3306; - 成员被隔离或失去多数派时,本机 Router 会主动拒绝读写连接(fail-safe),不会提供过期读。
实测参考:主库优雅停机的写中断约 3–4 秒,主库崩溃(kill -9)约 20 秒出头(默认驱逐参数),滚动重启期间从库重启对客户端无感。
管理数据库与用户
在清单中修改 mysql_databases / mysql_users 声明,然后收敛:
./mysql.yml -l my-test # 全量收敛
./mysql.yml -l my-test -t mysql_provision # 只收敛业务对象(更快)
HA 集群的对象变更只会在当前主库执行并经复制生效。声明是增量语义:不会删库、删用户或回收授权;这三类操作请手工执行后同步清单。
修改集群参数
参数覆盖统一走 mysql_parameters:
mysql_parameters:
max_connections: 500
long_query_time: 2
./mysql.yml -l my-test --check # 预检:确认将要发生的变更
./mysql.yml -l my-test # 应用:自动编排滚动重启
滚动重启的编排语义(实测验证):
- 配置渲染后先做
mysqld --validate-config 校验,写错参数当场失败、不动服务; - 重启前检查集群健康:降级集群(少于 3 个 ONLINE)拒绝滚动重启,先恢复再变更;
- 从库逐台重启,每台等待回归
ONLINE 后再处理下一台;主库最后重启; - 主库重启会触发一次自动主从切换,预期数秒写中断;对切换时机敏感的业务请安排变更窗口。
单机集群直接原地重启。
主从切换
模块不自动编排计划内主从切换(Switchover);需要时用 AdminAPI 手工执行:
mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"127.0.0.1", port:3306,
"ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
dba.getCluster().setPrimaryInstance("10.10.10.12:3306"); // 指定新主库
'
切换后 Router 自动跟随,无需重新配置。之后重跑 ./mysql.yml -l <集群> 确认收敛(运行时主库位置不属于声明状态,剧本不会把主库切回去)。
成员故障与自愈
故障中无需人工介入:主库崩溃后 MGR 约 20 秒内选出新主,Router 自动改道;崩溃成员由 systemd 拉起并自动重新入组。以下场景才需要动手:
| 现象 | 处理 |
|---|
某成员 MEMBER_STATE 长期 OFFLINE(进程在、GR 停了) | 重跑 ./mysql.yml -l <集群>,剧本会将其 rejoin 回集群 |
成员反复无法入组,日志报 peers not configured | 同上:收敛会把 group_replication_group_seeds 钉回声明值 |
| 网络分区恢复后成员未回归 | 等待约 1 分钟自动重连;仍未回归则重跑剧本 |
全部成员 OFFLINE | 完全停机场景,见完全停机恢复 |
| 机器损坏无法修复 | 见替换故障成员 |
对应告警:MySQLClusterMemberOffline(WARN)、MySQLClusterNoPrimary / MySQLClusterQuorumLost(CRIT)。
替换故障成员
替换契约:新机器复用故障机的服务地址(清单不变),三步完成。假设 my-test-3(10.10.10.13)损坏:
# 1. 摘除故障成员。机器仍可达时使用退役剧本:
./mysql-rm.yml -l 10.10.10.13 -e mysql_safeguard=false -e mysql_rm_confirm=my-test-3
# 1b. 机器已彻底失联(SSH 不可达)时,剧本无法在其上执行;
# 改在任一健康成员上用 AdminAPI 强制摘除:
mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"127.0.0.1", port:3306,
"ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
dba.getCluster("my-test").removeInstance("10.10.10.13:3306", {force: true});'
# 2. 用同一地址准备新机器(重装系统),完成节点纳管
./node.yml -l 10.10.10.13
# 3. 对完整集群重新收敛:新成员将通过 Clone 自动重建数据并入组
./mysql.yml -l my-test --check
./mysql.yml -l my-test
要点:
- 第 1 步的本质是把该地址从集群 Metadata 中摘除——只有不在 Metadata 中的地址才会走全新 Clone 路径。退役剧本要求目标可达(在线 SECONDARY 或已脱离集群的成员);死机场景用 1b 的强制摘除代替;
- 新机器必须是全新状态(空数据目录、无 Router 密钥残留)——重装系统即可保证;带残留状态的"半新机器"会被预检或 Router 引导拒绝;
- Clone 会全量复制数据,耗时与数据量成正比,期间集群保持可用(1 主 1 从在线);
- 不支持在替换时更换成员地址,也不支持长期两节点运行。
下线与复活集群
下线整个集群(停止服务、注销监控、保留全部数据):
./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test
下线后每个成员的数据目录会留下退役标记 /var/lib/mysql/.pigsty-mysql-retired,它会阻止普通 mysql.yml 重新接管,防止误操作复活已退役实例。确认要原地复活时,删除标记后重新收敛:
ansible my-test -b -a 'rm -f /var/lib/mysql/.pigsty-mysql-retired'
./mysql.yml -l my-test
单机实例两条命令即可复活。HA 集群多一步:重跑会把服务拉起,但三个成员的 GR 都处于 OFFLINE(防脑裂:无人自举),剧本会以完全停机报错退出——继续按完全停机恢复第 3-4 步重建仲裁即可。
彻底销毁(删除数据目录、备份、软件包)不由剧本代劳,属于确认过备份的手工操作。
管理备份
systemctl list-timers mysql-backup.timer # 查看下次备份时间
systemctl start mysql-backup # 手工触发(HA 上仅主库真正执行,从库自动跳过)
journalctl -u mysql-backup --since today # 查看备份日志
备份目录布局(在当前主库的本地磁盘上):
/data/backups/mysql/<集群名>/
├── 20260729T053900Z/ # 一份已 prepare 的全量备份(可直接恢复)
│ ├── backup.ok # 提交标记:只有完整成功的备份才有
│ ├── backup.log # XtraBackup 执行日志
│ └── ... # InnoDB 数据文件
├── ... # 按 retention 保留最近 N 份
└── latest -> 20260729T053900Z # 原子指向最新一份
检查备份新鲜度(HA 集群要在所有成员上检查,因为备份跟随主库落盘):
ansible my-test -b -a 'ls -l /data/backups/mysql/my-test/latest'
备份告警缺口
当前版本没有备份新鲜度指标与告警:备份失败只能从 mysql-backup 日志(已接入 VictoriaLogs,Instance Dashboard 的 Router / Backup Logs 面板可查)发现。重要环境建议为备份日志配置外部巡检,并定期演练下文的恢复流程。
恢复物理备份
以下手册将单机实例恢复到最近一次备份(破坏性操作:备份之后的写入将丢失。恢复前确认 latest 时间戳可接受)。HA 集群的整簇重建同理:先在一台恢复出主库,其余成员走 Clone 重建。
# 0. 确认备份可用:必须存在 backup.ok
BK=/data/backups/mysql/my-meta/latest
sudo test -f $BK/backup.ok && sudo cat $BK/backup.ok
# 1. 停库并保留残骸(便于事后取证,确认无误后再删除)
sudo systemctl stop mysqld
sudo mv /var/lib/mysql /var/lib/mysql.destroyed
# 2. 回拷备份(备份已 prepare,无需再执行 --prepare)
sudo mkdir -p /var/lib/mysql && sudo chown mysql:mysql /var/lib/mysql && sudo chmod 750 /var/lib/mysql
sudo xtrabackup --copy-back --target-dir=$BK
sudo rm -f /var/lib/mysql/backup.ok /var/lib/mysql/backup.log # 清除随备份带入的记录文件
# 3. 重建备份不包含的运行目录
sudo mkdir -p /var/lib/mysql/binlog /var/lib/mysql/tmp
sudo chown -R mysql:mysql /var/lib/mysql
sudo chmod 750 /var/lib/mysql/binlog /var/lib/mysql/tmp
# 4. 重建 Pigsty 数据目录属主标记(cluster/instance/topology 按实际实例填写)
echo '{"version": 1, "cluster": "my-meta", "instance": "my-meta-1", "topology": "standalone"}' | \
sudo tee /var/lib/mysql/.pigsty-mysql-initialized > /dev/null
sudo chown mysql:mysql /var/lib/mysql/.pigsty-mysql-initialized
sudo chmod 600 /var/lib/mysql/.pigsty-mysql-initialized
# 5. EL 系统恢复 SELinux 上下文,然后启动
sudo restorecon -RF /var/lib/mysql 2>/dev/null || true
sudo systemctl start mysqld
# 6. 验证数据与 GTID 位点,并确认剧本可正常收敛
sudo mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -e 'SELECT @@gtid_executed; SHOW DATABASES;'
./mysql.yml -l my-meta # 应全绿收敛(changed=0 或仅例行项)
第 4 步的标记文件是 Pigsty 的数据目录属主凭证:缺失或内容不匹配时,mysql.yml 会拒绝接管恢复出的数据目录。HA 场景的 topology 值为 innodb_cluster,实例名按成员各自填写。
完全停机恢复
三个成员全部 OFFLINE(机房断电、级联故障)时,MGR 出于防脑裂考虑不会自动重建仲裁,mysql.yml 也会明确拒绝并在报错中给出指引。恢复流程:
# 1. 确认所有成员的 mysqld 进程在运行(systemd 通常已自动拉起),GR 全部 OFFLINE
ansible my-test -b -a "mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -NBe \
\"SELECT COALESCE((SELECT MEMBER_STATE FROM performance_schema.replication_group_members \
WHERE MEMBER_ID=@@server_uuid),'OFFLINE')\""
# 2. 选出数据最新的成员:比较各成员 GTID,选执行集最大(或相等任选)的一台
ansible my-test -b -a "mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -NBe 'SELECT @@gtid_executed'"
# 3. 在最新成员上用 AdminAPI 重建集群(把 10.10.10.12 换成第 2 步选出的地址)
mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"10.10.10.12", port:3306,
"ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
var c = dba.rebootClusterFromCompleteOutage("my-test");
print(c.status().defaultReplicaSet.status);'
# 4. 重跑剧本:仍处于 OFFLINE 的其余成员会被自动 rejoin,随后全绿收敛
./mysql.yml -l my-test
要点:
- 第 3 步通常已把所有可达成员一并带回;个别成员仍 OFFLINE 时由第 4 步的剧本收敛完成 rejoin,无需逐台手工处理;
- 若在少数成员上重建(其余机器已损坏),先完成重建恢复写入,再按替换故障成员补齐;
- 重建完成前集群无法写入(
super_read_only);多数场景下各成员仍可只读访问,个别曾被驱逐的成员可能处于 offline_mode 拒绝普通连接; - 平台默认
sql_require_primary_key=ON 已从源头拦截会阻塞该流程的无主键表。
平台密码的边界
三个平台密码的运维边界(详见参数参考):
mysql_monitor_password:改清单后重跑即可轮换(Exporter 配置随之更新);mysql_root_password:不支持隐式重置。轮换流程:主库手工 ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; → 更新清单 → 重跑收敛凭据文件;mysql_cluster_password:HA 集群中与 Metadata 和 Router 密钥环绑定,普通重跑拒绝轮换(单机无此限制,改清单重跑即生效);当前版本没有 HA 自动轮换流程,如必须轮换请通过 AdminAPI 手工操作并同步全部成员的凭据文件后再更新清单。
4 - 预置剧本
使用 mysql.yml 与 mysql-rm.yml 完成部署、收敛、参数变更、成员退役与集群下线。
MYSQL 模块提供两个剧本:mysql.yml 负责部署与收敛,mysql-rm.yml 负责退役与下线。两者都是收敛式设计:描述期望状态,重复执行安全。
mysql.yml
对选中集群执行「检查 → 安装 → 引导 → 接入 → 业务对象 → 备份 → 监控」的完整收敛:
./mysql.yml -l my-test --check # 预检:校验声明与现场,不做变更
./mysql.yml -l my-test # 收敛一个集群(必须选中全部成员)
./mysql.yml # 收敛清单中所有 MySQL 集群
使用约定:
- HA 集群必须整簇选择:
-l 只选中部分成员会在预检被拒绝(防止拓扑分歧);可以同时选中多个完整集群或不加 -l; - 幂等:现场已符合声明时重跑为
changed=0,秒级完成;AdminAPI 成员操作(rejoin/Clone)之后的下一次运行可能出现一次收敛性 changed(复制种子钉回声明值),属预期行为; - check 模式:对全新节点只能预演到软件包安装(后续步骤依赖已安装的现场),对已部署集群可完整预演;
- 首次三节点部署约 2 分钟:证书签发 → 配置初始化 → AdminAPI 建群 → 两个从库 Clone → 每成员 Router 引导 → 业务对象 → 备份与监控注册。
执行阶段与任务标签
mysql
├── mysql_check # 校验身份、平台、凭据、参数与数据目录属主(always)
├── mysql_install # 安装固定的 MySQL 8.4 平台软件包
├── mysql_bootstrap
│ ├── mysql_cert # 签发并安装节点 TLS 叶证书
│ ├── mysql_config # 渲染配置(含 mysql_parameters)、初始化空数据目录
│ ├── mysql_launch # 启动/滚动重启 mysqld,收敛 root 与 AdminAPI 身份
│ └── mysql_cluster # 建立或收敛三节点 InnoDB Cluster(rejoin/Clone)
├── mysql_access
│ └── mysql_router # 在 HA 成员上引导并校验 Router
├── mysql_provision # 收敛平台身份与声明的业务库、用户
├── mysql_backup # 安装备份脚本与每日定时器
├── mysql_monitor # 配置 Exporter 并注册监控 Target
└── mysql_done # 输出实例摘要
常用标签化运行:
./mysql.yml -l my-test -t mysql_provision # 只收敛业务库与用户
./mysql.yml -l my-test -t mysql_backup # 只收敛备份配置与定时器
./mysql.yml -l my-test -t mysql_monitor # 只收敛 Exporter 与监控注册
参数与配置变更建议执行完整剧本(涉及滚动重启编排,见下节)。
配置变更与滚动重启
mysql_launch 阶段包含变更编排逻辑,当配置文件、证书或 systemd 单元发生变化时:
- 健康前置检查:HA 集群必须 3 成员
ONLINE 才允许滚动重启,降级集群直接拒绝(先修复后变更); - 从库先行:按当前运行时角色(而非
mysql_seq)排序,从库逐台重启并等待回归 ONLINE; - 主库殿后:最后重启主库,触发一次自动切换(秒级写中断)。
单机集群直接原地重启。配置渲染阶段的 mysqld --validate-config 保证非法参数在触碰服务之前失败。
安全护栏
mysql.yml 的预检与收敛在以下情况主动拒绝,错误信息会说明原因与处置:
| 拒绝场景 | 说明 |
|---|
| 部分成员选择 | HA 操作必须选中全部成员 |
| 非法拓扑 | 成员数只能是 1 或 3,mysql_seq 必须连续 |
| 平台不支持 | 架构/系统不在支持矩阵(如 Ubuntu ARM64) |
| 占位密码 | CHANGE_ME 前缀密码未替换 |
| 数据目录不属主 | 数据目录缺失 Pigsty 标记,或标记属于其他集群/实例/拓扑 |
| 退役标记存在 | mysql-rm.yml 下线过的实例,防止误复活 |
| 隐式密码变更 | mysql_cluster_password 或现场 root 密码与声明不一致 |
| 非法参数覆盖 | mysql_parameters 含保留参数、畸形键名或多行值 |
| 降级集群滚动重启 | 少于 3 成员 ONLINE 时拒绝配置类重启 |
| 非全新 Clone 目标 | 更换的成员必须是空数据目录的全新机器 |
| 完全停机 | 不自动重建仲裁,报错给出手工恢复指引 |
这些护栏意味着:任何单次误操作都不应造成数据丢失。绕过护栏的每个动作(删标记、清数据目录)都必须是显式的人工决定。
mysql-rm.yml
退役剧本接受三种范围,全部需要双重确认(mysql_safeguard=false + mysql_rm_confirm 精确等于目标名):
# 退役 HA 集群中的一个成员(目标须可达:在线 SECONDARY 或已脱离集群的成员)
./mysql-rm.yml -l 10.10.10.13 --check -e mysql_safeguard=false -e mysql_rm_confirm=my-test-3
./mysql-rm.yml -l 10.10.10.13 -e mysql_safeguard=false -e mysql_rm_confirm=my-test-3
# 下线整个 HA 集群
./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test
# 下线单机实例
./mysql-rm.yml -l my-meta -e mysql_safeguard=false -e mysql_rm_confirm=my-meta
执行内容与边界:
- 单成员退役:用 AdminAPI(
force: false)从集群摘除 ONLINE SECONDARY(或确认已脱离集群成员的摘除状态),随后停止本机服务。摘除脚本在目标机上执行,因此要求目标可达;机器已死亡时改用手工强制摘除(见替换故障成员)。不允许直接退役主库(先 setPrimaryInstance 切走),也不允许一次退役 3 成员中的 2 个; - 整簇下线:停止 Router 与备份定时器 → 从库先停、主库最后 → 注销 Exporter 与监控 Target;
- 每个数据目录写入退役标记
.pigsty-mysql-retired,阻止普通 mysql.yml 重新接管; - 保留一切数据:数据目录、备份、配置、证书、软件包、Metadata、Router 身份全部原样保留。彻底销毁是另一件事,请在确认备份后手工执行。
预览模式(--check)会完整展示将要发生的动作而不触碰现场。
剧本边界
以下操作不属于剧本职责,对应的人工流程见日常管理:
- 计划内主从切换(
setPrimaryInstance); - 不可达死机成员的强制摘除(
removeInstance + force: true); - 完全停机后的仲裁重建(
rebootClusterFromCompleteOutage); - 物理备份恢复(XtraBackup copy-back 手册);
- 删除数据目录 / 备份 / 退役标记等销毁类动作;
- 拓扑变形(1→3、3→5)与成员改址。
5 - 监控告警
MySQL 指标采集、Grafana Dashboard、告警规则与日志查询。
MYSQL 模块复用 Pigsty 的可观测性基座:指标经 mysqld_exporter 进入 VictoriaMetrics,错误日志经 Journald/Vector 进入 VictoriaLogs,Grafana 提供 5 个预置 Dashboard,vmalert 加载 68 条衍生规则与 27 条告警规则。
采集架构
每个 MySQL 节点运行一个 mysqld_exporter(端口 9104),以最小权限监控账号(dbuser_monitor@'127.0.0.1')采集服务器与 MGR 指标。部署时在 Infra 节点生成文件发现 Target:
/infra/targets/mysql/<实例名>.yml # 如 my-test-1.yml
VictoriaMetrics 的 mysql 抓取任务消费该目录。mysql_exporter_enabled: false 会把 Target 收敛为空;只有 mysql-rm.yml 才删除 Target 文件。
Exporter 启用的采集器包括:全局状态/变量、Binlog 尺寸、InnoDB 指标、进程列表、性能模式语句摘要(Top 50 摘要)、表/索引 IO 等待,以及 MGR 成员与复制统计。
标签模型
所有 MySQL 指标携带统一标签:
| 标签 | 含义 | 示例 |
|---|
job | 抓取任务 | mysql |
cls | 集群名 | my-test |
ins | 实例名 | my-test-1 |
ip | 成员地址 | 10.10.10.11 |
topology | 拓扑类型 | innodb_cluster / standalone |
衍生规则以 mysql:ins:*(实例级)与 mysql:cls:*(集群级)命名,完整清单见指标定义。
Grafana Dashboard
集群健康速读:mysql:cls:health 取值 2(健康)/ 1(降级仍可写)/ 0(危险或不可写),Overview 首屏的 Healthy Clusters 与 Cluster Health 时间线都基于它。
MySQL Group Replication Dashboard 仅对 innodb_cluster 拓扑有意义;选中单机集群时相关面板显示 No data 属预期现象。
告警规则
27 条告警规则按严重级分层(severity:CRIT / WARN / INFO),关键规则如下:
可用性与集群(响应优先)
| 告警 | 级别 | 触发条件 |
|---|
MySQLInstanceDown | CRIT | 实例连接失败超 1 分钟 |
MySQLClusterNoPrimary | CRIT | 集群无 ONLINE 主库超 1 分钟 |
MySQLClusterQuorumLost | CRIT | ONLINE 成员不足多数派超 1 分钟 |
MySQLClusterMultiplePrimary | CRIT | 出现多主(30 秒即告,脑裂信号) |
MySQLSecondaryWritable | CRIT | 从库可写超 2 分钟(数据发散风险) |
MySQLClusterMemberOffline | WARN | 声明成员离组超 5 分钟 |
MySQLPrimaryReadOnly | WARN | 主库只读超 5 分钟 |
MySQLExporterDown | WARN | Exporter 抓取失败超 2 分钟 |
容量与性能(观察优先)
连接压力(MySQLConnectionsHigh WARN 80% / MySQLConnectionsCritical CRIT 95%)、复制队列(MySQLGRQueueHigh WARN / MySQLGRQueueCritical CRIT)、流控(MySQLGRFlowControlHigh)、InnoDB(MySQLBufferPoolWaits、MySQLInnoDBLogWaits、MySQLRedoCapacityHigh、MySQLDeadlocksHigh、MySQLHistoryListLarge),以及 INFO 级的慢查询、磁盘临时表、全表连接、缓冲池命中率与重启提示。
实测行为参考:主库崩溃切换(约 20 秒)只会产生 pending 不会误报;真正的完全停机会在 2 分钟内让 ClusterNoPrimary 与 QuorumLost 进入 firing。
日志查询
MySQL 错误日志双写:本地文件 /var/log/mysql/error.log + Syslog → Journald → Vector → VictoriaLogs。日志条目携带 app=mysqld-<实例名> 标识,Dashboard 的日志面板开箱可用,也可直接用 LogsQL 查询:
# 某实例最近的错误日志
curl -s http://<infra>:9428/select/logsql/query \
-d 'query=app:mysqld-my-test-1 level:err _time:1h'
# 某集群全部 MySQL 相关日志(含备份任务)
curl -s http://<infra>:9428/select/logsql/query \
-d 'query=job:syslog cls:my-test (app:~"mysqld-" OR unit:mysql-backup) _time:1h | limit 100'
注意日志的 cls 标签取自节点集群名(node_cluster)——像配置示例那样保持 node_cluster 与 mysql_cluster 一致,指标与日志的标签才能对齐。
已知边界:
- 慢查询日志(
slow.log,阈值 1 秒)仅落本地文件,不进入 VictoriaLogs;分析慢查询请登录实例查看文件,或使用性能模式语句摘要指标(mysql:ins:statement_latency 等); - Router 运行日志写入
/var/log/mysqlrouter/,同样仅限本地文件。
验证监控链路
部署后可用以下命令自检全链路:
# Exporter 本体
curl -s http://<成员>:9104/metrics | grep -E '^mysql_up '
# VictoriaMetrics 抓取与衍生规则
curl -s 'http://<infra>:8428/api/v1/query?query=mysql_up'
curl -s 'http://<infra>:8428/api/v1/query?query=mysql:cls:health'
# vmalert 规则装载(应看到 mysql-rules 与 mysql-alerts 两组)
curl -s 'http://<infra>:8880/api/v1/rules' | grep -o '"name":"mysql-[a-z]*"'
# 日志入库
curl -s 'http://<infra>:9428/select/logsql/query' -d 'query=app:~"mysqld-" _time:1h | stats by (app) count()'
6 - 指标定义
MySQL 模块的标签模型、衍生指标字典与原始指标族。
MYSQL 模块的指标来自 mysqld_exporter(原始指标,mysql_ 前缀)与 vmalert 衍生规则(mysql:ins:* / mysql:cls:*)。Dashboard 与告警优先建立在衍生指标之上,本页是衍生指标的完整字典。
公共标签
所有指标携带 job=mysql 与身份标签 cls / ins / ip / topology(取值 standalone 或 innodb_cluster)。实例级衍生指标保留全部身份标签,集群级指标聚合到 cls + topology。
可用性
| 指标 | 含义 |
|---|
mysql:ins:exporter_up | Exporter 抓取是否成功(传输层健康) |
mysql:ins:up | MySQL 连接探测是否成功(数据库健康) |
mysql:ins:uptime | 实例运行时长(秒) |
mysql:cls:instances | 集群声明实例数 |
mysql:cls:up | 集群在线实例数 |
mysql:cls:health | 集群健康度:2 健康 / 1 降级可写 / 0 危险 |
mysql:cls:health 对 HA 集群综合仲裁、单主与全员在线状态;对单机取 2 × mysql:cls:up。
工作负载
| 指标 | 含义 |
|---|
mysql:ins:qps | 每秒问询数(Questions) |
mysql:ins:tps | 每秒事务数(Commit + Rollback) |
mysql:ins:read_qps / mysql:ins:write_qps | 读类 / 写类命令速率 |
mysql:ins:row_ops | InnoDB 行操作速率(读/插/改/删分维度) |
mysql:ins:statement_rate | 性能模式语句执行速率 |
mysql:ins:statement_latency | 语句平均时延(秒) |
mysql:ins:rows_examined_per_query | 平均每查询扫描行数 |
mysql:ins:statement_errors | 语句错误率 |
mysql:ins:slow_queries / mysql:ins:slow_query_ratio | 慢查询速率与占比 |
mysql:ins:no_index_queries | 未走索引查询速率 |
连接与会话
| 指标 | 含义 |
|---|
mysql:ins:connections | 当前连接数(Threads_connected) |
mysql:ins:connection_usage | 连接数 / max_connections 使用率 |
mysql:ins:connection_rate | 新建连接速率 |
mysql:ins:threads_running / mysql:ins:threads_cached | 活跃 / 缓存线程数 |
mysql:ins:aborted_connects / mysql:ins:aborted_clients | 失败握手 / 异常断开速率 |
mysql:ins:connection_errors | 连接错误总速率 |
mysql:ins:rx_bytes / mysql:ins:tx_bytes | 网络收 / 发字节率 |
临时表、扫描与缓存
| 指标 | 含义 |
|---|
mysql:ins:tmp_tables / mysql:ins:tmp_disk_tables | 内存 / 磁盘临时表创建速率 |
mysql:ins:tmp_disk_ratio | 磁盘临时表占比 |
mysql:ins:full_joins / mysql:ins:full_scans | 无索引连接 / 全表扫描速率 |
mysql:ins:sort_merge_passes | 排序归并趟数(sort_buffer 不足信号) |
mysql:ins:table_open_cache_hit_ratio | 表缓存命中率 |
mysql:ins:open_files_usage | 打开文件数使用率 |
InnoDB
| 指标 | 含义 |
|---|
mysql:ins:buffer_pool_hit_ratio | 缓冲池命中率 |
mysql:ins:buffer_pool_usage / mysql:ins:buffer_pool_dirty_ratio | 缓冲池使用率 / 脏页占比 |
mysql:ins:buffer_pool_waits | 缓冲池空闲页等待速率(内存压力信号) |
mysql:ins:data_read_bytes / mysql:ins:data_write_bytes | 数据文件读 / 写字节率 |
mysql:ins:data_reads / mysql:ins:data_writes / mysql:ins:data_fsyncs | 数据文件 IO 与 fsync 速率 |
mysql:ins:redo_bytes | Redo 写入字节率 |
mysql:ins:redo_utilization | Redo 容量使用率(检查点落后度) |
mysql:ins:log_waits | Redo 缓冲等待速率 |
mysql:ins:row_lock_waits / mysql:ins:row_lock_time | 行锁等待速率 / 耗时 |
mysql:ins:deadlocks | 死锁速率 |
mysql:ins:history_list_length | Purge 滞后(历史链表长度) |
mysql:ins:binlog_bytes | Binlog 当前磁盘占用总量(字节) |
Group Replication
实例级成员状态(取值为 1 或缺失——不满足条件时序列不存在,告警据此用 unless 判断):
| 指标 | 含义 |
|---|
mysql:ins:gr_member | 本实例处于任意 MGR 成员状态 |
mysql:ins:gr_online | 本实例 ONLINE |
mysql:ins:gr_primary / mysql:ins:gr_secondary | 本实例为 ONLINE 主库 / 从库 |
集群级仲裁与拓扑:
| 指标 | 含义 |
|---|
mysql:cls:gr_online_members | ONLINE 成员数 |
mysql:cls:gr_primary_members | ONLINE 主库数 |
mysql:cls:gr_quorum | 是否保有多数派(0/1) |
mysql:cls:gr_single_primary | 是否恰好单主(0/1) |
复制管道(认证与应用):
| 指标 | 含义 |
|---|
mysql:ins:gr_certifier_queue / mysql:ins:gr_applier_queue | 认证 / 应用队列积压事务数 |
mysql:ins:gr_certifier_queue_ratio / mysql:ins:gr_applier_queue_ratio | 队列积压相对流控阈值的占比 |
mysql:ins:gr_checked_rate / mysql:ins:gr_applied_rate | 事务认证 / 应用速率 |
mysql:ins:gr_conflict_rate | 认证冲突速率(多写冲突信号,单主下应为 0) |
原始指标族
衍生指标未覆盖的细节可直接查询 Exporter 原始指标,常用族:
| 前缀 | 内容 |
|---|
mysql_up / up | 数据库连接探测 / 抓取状态 |
mysql_global_status_* | SHOW GLOBAL STATUS 全量计数器 |
mysql_global_variables_* | 关键系统变量(如 max_connections) |
mysql_perf_schema_events_statements_* | 语句摘要(按 digest Top 50) |
mysql_perf_schema_table_io_waits_* / ..._index_io_waits_* | 表 / 索引 IO 等待 |
mysql_perf_schema_replication_group_member_info | MGR 成员状态(member_state / member_role 维度) |
mysql_perf_schema_transactions_* / mysql_perf_schema_conflicts_detected_total | MGR 认证队列、应用队列与冲突统计 |
mysql_binlog_* | Binlog 文件数与尺寸 |
mysql_info_schema_processlist_* | 会话按状态分布 |
在 VictoriaMetrics 的 vmui(/select/vmui)中以 mysql_ 前缀浏览即可获得完整清单。
7 - 常见问题
Pigsty MySQL 试点模块常见问题与故障排查。
当前 MYSQL 模块是什么成熟度?
Pilot 试点模块,定位「简单、廉价、够用」的 MySQL 集群。部署收敛、高可用切换、每日备份、监控告警四大核心能力经过系统性实测(含故障注入与完全停机演练);恢复类破坏性流程刻意保留为手工操作并配有操作手册。不追求与 PGSQL 模块同级的完备度:没有 PITR、没有接入层 VIP/DNS、没有自动扩缩容。用于严肃生产环境前,请按业务要求验证并演练恢复流程。
为什么固定 MySQL 8.4,不能选版本?
MYSQL 是「固定平台」而不是通用安装器:Server、Client、Shell、Router、XtraBackup 全线锁定 8.4 LTS,保证组件间兼容与行为可预期,省去版本矩阵的测试与踩坑成本。这是试点模块控制复杂度的核心取舍;需要其他版本或深度定制时,本模块不适合。
为什么只支持 1 或 3 节点?怎么扩容?
拓扑固定为单机或三节点单主 InnoDB Cluster,预检拒绝其他成员数,也不支持 1→3 原地升级(数据目录标记会拦截拓扑变更)。原因:动态成员数会引入仲裁、Router 重引导与收敛路径的组合复杂度,超出试点模块的收益。
扩容路径:
- 纵向:换更大机器,走同地址替换逐台完成(滚动换硬件);
- 单机 → HA:新建三节点集群,用
mysqldump/mysqlsh util.dumpInstance 逻辑迁移; - 读扩展:只读流量走
6447 由两个从库分担。
为什么建表报 ERROR 3750(要求主键)?
平台默认 sql_require_primary_key=ON。无主键表在 Group Replication 下只读不可写,还会在完全停机恢复时阻塞 AdminAPI 重建集群——与其让它在灾难现场爆炸,不如在建表时拦截。请为所有表定义主键;接入既有系统确实无法改表时,可用参数覆盖关闭:
mysql_parameters: { sql_require_primary_key: false }
单机实例同样默认开启,以保证未来能平滑迁往 HA。
为什么 Ubuntu/Debian ARM64 被拒绝?
Oracle 的 APT 仓库没有为 MySQL 8.4 提供 arm64 软件包,这不是 Pigsty 能绕过的。ARM 环境(含 Apple Silicon 上的虚拟机)请使用 EL 9/10(Rocky/Alma),Oracle 的 YUM 仓库提供完整 aarch64 支持。
客户端应该连哪个端口?TLS 是必须的吗?
HA 集群连任一成员的 6446(读写)/6447(只读),Router 自动跟随主从切换;单机直连 3306。TLS 是强制的:服务端 require_secure_transport=ON,明文连接直接被拒(ERROR 3159)。普通客户端默认的 PREFERRED 模式即会自动协商加密(只有显式 DISABLED 才会被拒);建议显式 VERIFY_CA 并信任 /etc/pki/ca.crt。
Router 是每节点本地部署,没有统一 VIP。应用侧请使用多地址 DSN(把三个成员的 6446 都写进连接串)以规避单节点故障。
主库切走了,会自动切回来吗?
不会,也不需要。mysql_seq=1 只是首次引导顺序,运行时主库由 MGR 选举决定;故障切换或滚动重启后主库落在哪台都是合法状态,重跑剧本不会移动主库。需要指定主库时用 setPrimaryInstance 手工切换。
某个成员掉线了怎么办?
绝大多数情况下什么都不用做:进程崩溃由 systemd 拉起并自动重新入组(实测主库崩溃约 20 秒完成切换与自愈)。如果成员长期停留在 OFFLINE(如网络分区恢复后、或 STOP GROUP_REPLICATION 之后),重跑一次 ./mysql.yml -l <集群> 即可将其 rejoin。仍失败时看剧本报错——错误信息会说明原因与下一步动作。
三台全挂了怎么恢复?
这是唯一需要手工介入的可用性场景(防脑裂的刻意设计):在数据最新的成员上执行 dba.rebootClusterFromCompleteOutage(),然后重跑剧本收敛其余成员。完整步骤见完全停机恢复手册。mysql.yml 在这种状态下的报错会直接给出该指引。
备份在哪里?能恢复到任意时间点吗?
备份是每日一次的全量物理备份,落在当前主库的 /data/backups/mysql/<集群>/ 下(主从切换后新备份跟随新主库,检查时要看所有成员)。没有增量与 Binlog 归档,因此不支持 PITR:单机的恢复点就是最近一次备份(最坏损失一天写入);HA 集群的数据安全主要靠三副本同步复制,备份用于兜底与整簇重建。恢复步骤见恢复物理备份手册。异地容灾请自行同步备份目录。
备份失败会有告警吗?
当前版本没有备份专属指标与告警(已知缺口)。备份日志已接入 VictoriaLogs(unit:mysql-backup),Instance Dashboard 的 Router / Backup Logs 面板可查;重要环境建议对备份日志做外部巡检,并定期做恢复演练验证备份可用性。
为什么 mysql_parameters 里有些参数被拒绝?
身份(server_id、datadir、端口等)、复制(gtid_mode、log_bin、group_replication_*)与 TLS 全族是平台保证的一部分,被列为保留参数——覆盖它们会破坏集群身份或安全底线,预检直接拒绝(- 与 _ 写法同判)。其余参数放行,且渲染后仍经 mysqld --validate-config 校验。完整保留清单见参数参考。
修改参数会导致停机吗?
会有一次可控的秒级抖动:参数变更触发编排式滚动重启,从库逐台先行(客户端无感),主库最后重启并触发一次自动切换(实测写中断约 3–4 秒)。降级集群会拒绝滚动重启,避免雪上加霜。对切换敏感的业务请安排变更窗口。
怎么修改 root 或平台密码?
mysql_monitor_password:改清单重跑即可(Exporter 配置随之刷新);mysql_root_password:为防止误配置静默改密,剧本拒绝隐式重置——先手工 ALTER USER 'root'@'localhost' ...,再更新清单重跑;mysql_cluster_password:HA 集群中与 Metadata、Router 密钥环绑定,普通重跑拒绝轮换(单机改清单重跑即生效),当前无 HA 自动轮换流程;如必须轮换,请通过 AdminAPI 手工操作并同步各成员凭据文件后再更新清单。
下线的集群怎么复活?误删了退役标记会怎样?
mysql-rm.yml 下线时保留全部数据并写入退役标记;复活 = 删除各成员的 /var/lib/mysql/.pigsty-mysql-retired 后重跑 mysql.yml(见下线与复活集群)。单机两步即可;HA 集群还需按完全停机恢复重建仲裁。标记的意义是防止「下线后被无意重新拉起」;数据目录属主校验(.pigsty-mysql-initialized)独立存在,删除退役标记不会让别的集群接管这份数据。
conf/mysql.yml 模板怎么和这个模块对不上?
那是 OpenHalo 模板——基于 PostgreSQL 内核的 MySQL 线缆协议兼容方案(pg_mode: mysql),与本模块无关。原生 MySQL 模块的参考模板是 conf/demo/mysql.yml。选型参考:需要真 MySQL 生态兼容用本模块;PG 基础设施上跑 MySQL 协议应用可考虑 OpenHalo。
剧本失败显示 no ONLINE member holds the cluster?
这是完全停机(或仅存成员不可达)的判定:没有任何 ONLINE 成员持有集群。按报错给出的指引执行完全停机恢复。如果实际上有成员在线却报此错,先检查 seq=1 协调成员(收敛脚本在其上执行)到各成员 3306 的连通性,以及该成员上的 CA(/etc/pki/ca.crt)是否就位。
监控没有数据 / Dashboard 空白?
按链路排查:curl http://<成员>:9104/metrics | grep mysql_up(Exporter 本体)→ Infra 上确认 /infra/targets/mysql/ 有实例文件 → VictoriaMetrics 查询 up{job="mysql"}。GR Dashboard 选中了单机集群时 MGR 面板显示 No data 属正常现象。完整自检命令见监控告警。