Files
xinfra/ansible/templates/mysql-instance.cnf.j2
T
Hungerdream 454df86021 fix(ansible): 一主多从从库强制只读
- mysql-instance.cnf.j2 按 mysql_node_role=replica 注入 read-only/super-read-only,
  阻止业务直接写入从库导致主从数据分叉(复制线程与复制管理语句不受影响)
- 账号配置任务在从库上临时放开只读、配置完成后回锁,
  避免 cnf 只读拒绝 ALTER/CREATE USER;主库与 standalone 不受影响
2026-07-31 18:49:21 +08:00

141 lines
7.9 KiB
Django/Jinja
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# XINFRA MySQL 实例配置文件(Jinja2 模板)
# =============================================================================
# 此文件由 Playbook 自动生成,禁止手动编辑
# 修改配置请通过平台参数传递,重新部署即可
# =============================================================================
# 客户端连接配置(mysql 命令行工具使用)
[client]
socket={{ mysql_run_dir }}/mysql.sock # Unix socket 连接路径(本地连接更快)
port={{ mysql_port_value }} # TCP 端口(远程连接使用)
# =============================================================================
# MySQL 服务端核心配置
# =============================================================================
[mysqld]
# --- 基础运行参数 ---
user=mysql # 运行用户(与 systemd 单元一致)
basedir=/usr # MySQL 安装根目录(Ubuntu apt 安装位置)
datadir={{ mysql_data_dir }} # 数据目录(所有表、索引、数据文件)
tmpdir={{ mysql_tmp_dir }} # 临时文件目录(排序、临时表等)
socket={{ mysql_run_dir }}/mysql.sock # Unix socket 路径(本地客户端连接)
pid-file={{ mysql_run_dir }}/mysql.pid # 进程 PID 文件路径
port={{ mysql_port_value }} # 监听端口
bind-address=0.0.0.0 # 监听所有网络接口(允许远程连接)
skip-name-resolve=ON # 跳过 DNS 解析(提升连接速度,授权时需用 IP)
server-id={{ mysql_server_id_value }} # 服务器唯一 ID(复制必须,全机唯一)
local-infile=OFF # 禁用 LOAD DATA LOCAL(安全考虑,防止读取客户端文件)
# --- 字符集 / 排序规则 / 时区 / 标识符大小写 ---
character-set-server={{ mysql_character_set }} # 服务端字符集,默认 utf8mb4
collation-server={{ mysql_collation }} # 排序规则,默认 utf8mb4_general_ci
default-time-zone={{ mysql_timezone }} # 默认时区,东八区
lower-case-table-names={{ mysql_lower_case_table_names }} # 表名大小写敏感:1=不敏感(Linux 推荐)
# --- 错误日志 / 慢查询日志 ---
log-error={{ mysql_log_dir }}/error.log # 错误日志路径
slow-query-log=ON # 启用慢查询日志
slow-query-log-file={{ mysql_log_dir }}/slow.log # 慢查询日志路径
long-query-time={{ mysql_long_query_time }} # 慢查询阈值(秒),超过此时间记录
# =============================================================================
# Binlog 配置(用于数据恢复 PITR + 复制基础)
# =============================================================================
log-bin={{ mysql_binlog_dir }}/binlog # binlog 文件前缀(二进制日志)
binlog-format=ROW # 格式:ROW(行变更),复制最安全
sync-binlog={{ mysql_sync_binlog }} # 每次提交同步 binlog 到磁盘,1=最安全
max-binlog-size={{ mysql_max_binlog_size }} # 单个 binlog 文件最大大小
binlog-expire-logs-seconds={{ mysql_binlog_expire_logs_seconds }} # binlog 过期时间(秒),默认 7 天
# --- 非 standalone 拓扑才启用的复制参数 ---
{% if topology != 'standalone' %}
gtid-mode=ON # 启用 GTID(全局事务标识符)
enforce-gtid-consistency=ON # 强制 GTID 一致性(确保复制安全)
relay-log={{ mysql_binlog_dir }}/relay-bin # 中继日志路径(从库重放 binlog 使用)
{% if mysql_node_role | default('') == 'replica' %}
# 从库强制只读:阻止业务直接写入从库导致主从数据分叉
# 复制线程与 CHANGE REPLICATION SOURCE 等复制管理语句不受影响
read-only=ON
super-read-only=ON
{% endif %}
{% endif %}
# =============================================================================
# InnoDB 存储引擎核心配置
# =============================================================================
# 缓冲池大小:分配内存的 55%(MySQL 官方推荐 50%-75%)
innodb-buffer-pool-size={{ ((mysql_memory_mb_value | int) * 55 / 100) | int }}M
# 刷盘方式:O_DIRECT 绕过操作系统缓存,直接写磁盘
# 避免双重缓存,适合有电池保护写缓存的 RAID 控制器
innodb-flush-method=O_DIRECT
# 事务提交时刷日志到磁盘:1=每次提交都刷(最安全,性能最低)
innodb-flush-log-at-trx-commit={{ mysql_flush_log_at_trx_commit }}
# InnoDB I/O 能力:告诉 InnoDB 磁盘的 IOPS 能力
# 2000 适合 SSD,HDD 建议 200-400
innodb-io-capacity={{ mysql_io_capacity }}
# 最大连接数(按内存梯度计算,默认值见 Playbook)
max-connections={{ mysql_max_connections }}
# =============================================================================
# Redo Log 配置(InnoDB 崩溃恢复必需)
# =============================================================================
innodb-log-group-home-dir={{ mysql_redo_dir }} # redo log 目录
# MySQL 8.0.30+ 使用 innodb-redo-log-capacity 控制 redo log 总大小
# 旧版本使用 innodb-log-file-size 控制单个文件大小
{% if mysql_version_value in ['8.0', '8.4'] %}
innodb-redo-log-capacity={{ mysql_redo_capacity }}
{% else %}
innodb-log-file-size={{ mysql_redo_capacity }}
{% endif %}
# =============================================================================
# X Protocol 禁用(版本相关)
# =============================================================================
# X Protocol 是 MySQL 的 NoSQL 部分,我们不需要,禁用节省资源
{% if mysql_version_value in ['8.0', '8.4'] %}
mysqlx=0 # 8.0/8.4 直接禁用
{% elif mysql_version_value == '5.7' %}
loose-mysqlx=0 # 5.7 使用 loose 前缀(参数可能不存在)
{% endif %}
# =============================================================================
# Group Replication 配置(仅 mgr_3 拓扑)
# =============================================================================
# 注意:这里只做配置就绪,实际启动组复制需要平台侧执行 START GROUP_REPLICATION
{% if topology == 'mgr_3' %}
# 加载 Group Replication 插件
plugin-load-add=group_replication.so
# MySQL 8.0.26 之前需要设置事务写集提取(8.4 已移除此参数)
{% if mysql_version_value != '8.4' %}
transaction-write-set-extraction=XXHASH64 # 使用 XXHASH64 算法提取写集
{% endif %}
# GR 组 UUID(所有节点必须相同)
loose-group-replication-group-name={{ mgr_group_name }}
# 不在启动时自动加入组(由平台侧手动控制加入时机)
loose-group-replication-start-on-boot=OFF
# 本节点用于 GR 通信的地址和端口
loose-group-replication-local-address={{ ansible_host | default(inventory_hostname) }}:{{ mysql_gr_port_value }}
# 组内所有节点的种子列表(用于新节点发现和连接)
loose-group-replication-group-seeds={% for host in ansible_play_hosts_all %}{{ hostvars[host].ansible_host | default(host) }}:{{ mysql_gr_port_value }}{% if not loop.last %},{% endif %}{% endfor %}
# IP 白名单:只允许组内节点 IP 加入(安全限制)
loose-group-replication-ip-allowlist={% for host in ansible_play_hosts_all %}{{ hostvars[host].ansible_host | default(host) }}{% if not loop.last %},{% endif %}{% endfor %}
# 单主模式:只有 primary 节点可写,replica 只读(推荐生产使用)
loose-group-replication-single-primary-mode=ON
# 关闭强制更新检查:单主模式下不需要(多主模式才需要)
loose-group-replication-enforce-update-everywhere-checks=OFF
{% endif %}