跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

模块: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_databasesmysql_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。不依赖 ETCDPGSQL

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.ymlmysql-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_passwordmysql_monitor_passwordmysql_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 排序规则

每个条目只接受以上三个字段;额外字段会在预检阶段被拒绝。

声明是 增量收敛:重跑会创建缺失的库,但从列表删除条目不会 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
  • 不能声明 rootdbuser_monitordbuser_clusterdbuser_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 校验,非法参数在部署阶段即失败,不会影响运行中的服务;
  • 平台保留参数不可覆盖:身份与协议(userpid_fileserver_iddatadirsocketportbind_addressmysqlx_bind_addressreport_hostmysqlx 等)、复制与插件(gtid_modeenforce_gtid_consistencylog_binrelay_logplugin_load*cloneplugin_cloneplugin_mysqlxgroup_replication_* 等)以及 TLS(require_secure_transportssl_*)由角色统一管理,声明即拒绝;
  • 参数变更会触发 编排式滚动重启:从库先行、主库殿后。

内存基线无需配置:缓冲池为节点内存的 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 模块 13 项公开参数:11 项部署参数、2 项受保护移除参数,以及固定平台约定。

MYSQL 部署角色刻意只公开 11 项参数,移除角色另有 2 项受保护运维参数。软件版本、端口、目录、字符集、TLS 路径与定时器表达式由角色统一固定,内存基线按节点规格推导;需要调整服务器行为时使用 mysql_parameters


参数概览

参数 层级 默认值 说明
mysql_cluster 集群 必填 集群名与身份
mysql_seq 实例 必填 单机 1;HA 连续 1..3
mysql_root_password 集群 DBUser.Root 本地 root 密码
mysql_monitor_password 集群 DBUser.Monitor Exporter 监控身份密码
mysql_cluster_password 集群 DBUser.Cluster AdminAPI/Router/备份身份密码
mysql_databases 集群 [] 增量收敛的业务数据库
mysql_users 集群 [] 增量收敛的业务用户与授权
mysql_parameters 集群/实例 {} [mysqld] 参数覆盖
mysql_backup_enabled 集群 true 每日全量备份定时器
mysql_backup_repo 集群 见下文 本地备份目录与保留份数
mysql_exporter_enabled 集群 true Exporter 与监控 Target

移除参数由 mysql-rm.yml 使用:

参数 层级 默认值 说明
mysql_safeguard 全局/集群/命令行 true 默认拒绝执行移除
mysql_rm_confirm 命令行 '' 必须精确匹配实例名或集群名

旧版页面曾出现的 mysql_rolemysql_servicesmysql_packagesmysql_datamysql_portmysql_replication_*mysql_*_username 等变量已不属于公开接口,请勿使用。


身份参数

mysql_cluster

必填的集群身份,必须与清单分组名一致(预检要求成员位于同名分组)。字母、数字或下划线开头,可含 ._-,最长 63 字符:

mysql_cluster: my-test

用于生成实例名(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 前缀:

默认值为 DBUser.Root

mysql_root_password: DBUser.Root

首次启动时设置;此后如果现场密码与声明不一致,任务会 拒绝隐式重置 并明确报错——修改 root 密码需要先手工 ALTER USER 再同步清单。

mysql_monitor_password

dbuser_monitor@'127.0.0.1' 密码,供 mysqld_exporter 使用,仅限本机回环地址、最多 3 连接、只读权限:

默认值为 DBUser.Monitor

mysql_monitor_password: DBUser.Monitor

mysql_cluster_password

dbuser_cluster@'%'(要求 TLS)与 dbuser_backup@'localhost' 共用的平台密码,用于 AdminAPI 集群管理、Router 引导与 XtraBackup:

默认值为 DBUser.Cluster

mysql_cluster_password: DBUser.Cluster

HA 集群中该密码写入集群 Metadata 与 Router 密钥环,不能通过普通重跑轮换:现场值与声明不一致时预检直接拒绝。单机实例无此绑定,改清单重跑即生效。


业务对象

mysql_databases

增量收敛的业务数据库列表,仅接受 name / encoding / collate 三个字段:

mysql_databases:
  - { name: app }
  - { name: app2, encoding: utf8mb4, collate: utf8mb4_general_ci }

只创建与更新,不会因移除条目而删除数据库。写法与校验规则见 集群配置

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 校验,写错参数在部署阶段失败而不影响运行中的实例;
  • 保留参数拒绝覆盖-/_ 写法同判):userpid_fileserver_iddatadirsocketportbind_addressmysqlx_bind_addressreport_hostgtid_modeenforce_gtid_consistencylog_binrelay_logrequire_secure_transportssl_cassl_certssl_keyplugin_loadplugin_load_addcloneplugin_clonemysqlxplugin_mysqlx,以及 group_replication_*plugin_group_replication*plugin_mysqlx_bind_addressssl_* 全族;
  • 变更后重跑 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_safeguard

受保护移除的保险开关,默认值为 true。执行 mysql-rm.yml 时必须显式设置为 false,否则角色会拒绝继续:

./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test

mysql_rm_confirm

目标名称确认字符串,默认值为空。移除单个成员时必须精确等于实例名(例如 my-test-3);移除完整集群或单机实例时必须精确等于 mysql_cluster。该参数与 mysql_safeguard=false 缺一不可。


固定平台约定

以下值由角色固定或推导,不是 清单参数,列出供运维参考:

项目
软件版本 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);INFRA 角色以只读参考常量 mysql_exporter_port: 9104 生成监控配置,它不是 MYSQL 的公开参数
数据目录 /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            # 应用:自动编排滚动重启

滚动重启的编排语义(实测验证):

  1. 配置渲染后先做 mysqld --validate-config 校验,写错参数当场失败、不动服务;
  2. 重启前检查集群健康:降级集群(少于 3 个 ONLINE)拒绝滚动重启,先恢复再变更;
  3. 从库逐台重启,每台等待回归 ONLINE 后再处理下一台;主库最后重启;
  4. 主库重启会触发一次自动主从切换,预期数秒写中断;对切换时机敏感的业务请安排变更窗口。

单机集群直接原地重启。


主从切换

模块不自动编排计划内主从切换(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-310.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 单元发生变化时:

  1. 健康前置检查:HA 集群必须 3 成员 ONLINE 才允许滚动重启,降级集群直接拒绝(先修复后变更);
  2. 从库先行:按当前运行时角色(而非 mysql_seq)排序,从库逐台重启并等待回归 ONLINE
  3. 主库殿后:最后重启主库,触发一次自动切换(秒级写中断)。

单机集群直接原地重启。配置渲染阶段的 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

Dashboard 用途
MySQL Overview 舰队总览:集群清单、健康度、QPS/TPS、活跃告警与实例清单
MySQL Cluster 单集群视角:成员状态、负载、节点资源与集群日志
MySQL Instance 单实例细节:连接、语句、InnoDB、临时表、锁与实例日志
MySQL Group Replication MGR 专题:成员角色、认证/应用队列、流控、只读安全与 GR 日志
MySQL Alert 告警汇总与关键平台日志

集群健康速读: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(MySQLBufferPoolWaitsMySQLInnoDBLogWaitsMySQLRedoCapacityHighMySQLDeadlocksHighMySQLHistoryListLarge),以及 INFO 级的慢查询、磁盘临时表、全表连接、缓冲池命中率与重启提示。

实测行为参考:主库崩溃切换(约 20 秒)只会产生 pending 不会误报;真正的完全停机会在 2 分钟内让 ClusterNoPrimaryQuorumLost 进入 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_clustermysql_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(取值 standaloneinnodb_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_iddatadir、端口等)、复制(gtid_modelog_bingroup_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 属正常现象。完整自检命令见 监控告警