这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

模块:MySQL

使用 Pigsty 部署原生 MySQL 8.4 LTS 单机或三节点 InnoDB Cluster,附带 TLS、每日备份与完整监控。

MySQL 是世界上最流行的开源关系型数据库之一。Pigsty 的 MYSQL 模块在纳管节点上部署固定的原生 MySQL 8.4 LTS 平台:单机实例,或基于 Group Replication 的三节点单主 InnoDB Cluster,并统一管理 TLS、备份、监控与生命周期。


模块能力

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 RouterHA 拓扑感知入口,每个成员均部署RW 6446、RO 6447
MySQL ShellAdminAPI 生命周期管理本机控制面
XtraBackup每日全量物理备份本地备份仓库
mysqld_exporterMySQL 与 MGR 指标9104

角色创建并管理三个平台身份:

  • dbuser_cluster@'%':要求 TLS 的 AdminAPI 与 Router 引导身份(仅 HA 集群创建);
  • dbuser_monitor@'127.0.0.1':最小权限 Exporter 身份;
  • dbuser_backup@'localhost':本地 XtraBackup 身份。

平台支持

原生软件包平台门禁为:

架构支持的系统
x86_64EL 8/9/10、Debian 12/13、Ubuntu 22/24
aarch64EL 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_databases 是增量声明的数据库列表:

mysql_databases:
  - { name: app }                                              # 默认 utf8mb4 / utf8mb4_0900_ai_ci
  - { name: app2, encoding: utf8mb4, collate: utf8mb4_general_ci }
字段默认值说明
name必填库名,[A-Za-z0-9_$-],不能使用系统库名
encodingutf8mb4字符集
collateutf8mb4_0900_ai_ci排序规则
encryptfalse库级 DEFAULT ENCRYPTION;需自行配置 InnoDB Keyring 组件(平台未预置,未配置时建表会失败)

声明是增量收敛:重跑会创建缺失的库,但从列表删除条目不会 DROP 数据库。删除数据属于手工运维操作。


业务用户

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 校验,非法参数在部署阶段即失败,不会影响运行中的服务;
  • 平台保留参数不可覆盖:身份(server_iddatadirportsocketbind_addressreport_host 等)、复制(gtid_modelog_bingroup_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;单机场景的恢复点就是最近一次备份。

平台凭据

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_cluster集群必填集群名与身份
mysql_seq实例必填单机 1;HA 连续 1..3
mysql_root_password集群DBUser.Root本地 root 密码
mysql_monitor_password集群DBUser.MonitorExporter 监控身份密码
mysql_cluster_password集群DBUser.ClusterAdminAPI/Router/备份身份密码
mysql_databases集群[]增量收敛的业务数据库
mysql_users集群[]增量收敛的业务用户与授权
mysql_parameters集群/实例{}[mysqld] 参数覆盖
mysql_backup_enabled集群true每日全量备份定时器
mysql_backup_repo集群见下文本地备份目录与保留份数
mysql_exporter_enabled集群trueExporter 与监控 Target

旧版页面曾出现的 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 前缀:

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 校验,写错参数在部署阶段失败而不影响运行中的实例;
  • 保留参数拒绝覆盖-/_ 写法同判):userpid_fileserver_iddatadirsocketportbind_addressmysqlx_bind_addressreport_hostgtid_modeenforce_gtid_consistencylog_binrelay_logplugin_load_add,以及 group_replication_* 与 TLS 相关(require_secure_transportssl_*)全族;
  • 变更后重跑 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            # 应用:自动编排滚动重启

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

  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'

恢复物理备份

以下手册将单机实例恢复到最近一次备份(破坏性操作:备份之后的写入将丢失。恢复前确认 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 ReplicationMGR 专题:成员角色、认证/应用队列、流控、只读安全与 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),关键规则如下:

可用性与集群(响应优先)

告警级别触发条件
MySQLInstanceDownCRIT实例连接失败超 1 分钟
MySQLClusterNoPrimaryCRIT集群无 ONLINE 主库超 1 分钟
MySQLClusterQuorumLostCRITONLINE 成员不足多数派超 1 分钟
MySQLClusterMultiplePrimaryCRIT出现多主(30 秒即告,脑裂信号)
MySQLSecondaryWritableCRIT从库可写超 2 分钟(数据发散风险)
MySQLClusterMemberOfflineWARN声明成员离组超 5 分钟
MySQLPrimaryReadOnlyWARN主库只读超 5 分钟
MySQLExporterDownWARNExporter 抓取失败超 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_upExporter 抓取是否成功(传输层健康)
mysql:ins:upMySQL 连接探测是否成功(数据库健康)
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_opsInnoDB 行操作速率(读/插/改/删分维度)
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_bytesRedo 写入字节率
mysql:ins:redo_utilizationRedo 容量使用率(检查点落后度)
mysql:ins:log_waitsRedo 缓冲等待速率
mysql:ins:row_lock_waits / mysql:ins:row_lock_time行锁等待速率 / 耗时
mysql:ins:deadlocks死锁速率
mysql:ins:history_list_lengthPurge 滞后(历史链表长度)
mysql:ins:binlog_bytesBinlog 当前磁盘占用总量(字节)

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_membersONLINE 成员数
mysql:cls:gr_primary_membersONLINE 主库数
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_infoMGR 成员状态(member_state / member_role 维度)
mysql_perf_schema_transactions_* / mysql_perf_schema_conflicts_detected_totalMGR 认证队列、应用队列与冲突统计
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 属正常现象。完整自检命令见监控告警