docs(nacos-config): 添加 nacos_config 目录分析与修改指南

新增 g3fo-nacos-config 目录下的 SKILL.md 文档,详细说明 nacos_config 目录的结构、用户交互流程及配置文件的添加与修改规则。新增 yml-placement.md 文件,提供常见顶级键的插入顺序,以保持配置文件风格一致。
This commit is contained in:
2026-02-09 17:25:13 +08:00
parent 3ea09a1cdd
commit e798751e4b
5 changed files with 357 additions and 72 deletions
@@ -1,26 +1,32 @@
# MySQL 8.4 双主(Source-Source)同步部署文档(跨主机统一目录/容器名版)
> **AI 响应规范 (MySQL 执行策略)**:
>
> 1. **强制参数**: 所有 `docker exec` 命令必须包含 `-h127.0.0.1` 参数。
> 2. **双重输出**: 涉及 SQL 操作时,必须同时输出 `Docker 执行命令` 和 `纯 SQL 脚本`。
## 文档概述
你需要部署跨两台独立主机的 MySQL 8.4 双主双向复制集群,核心要求是:两台主机的容器名、目录路径统一使用 `mysql`(仅通过 IP 区分节点),保证两节点数据一致性,支持初始化、校验、宕机重启恢复及节点重建全流程。核心设计遵循:
+ **GTID + AUTO_POSITION**:重启后自动定位同步位点,减少人工干预;
+ **ROW 模式 binlog**:避免非确定性函数导致的数据不一致;
+ **持久化数据卷**:独立 Volume 保障容器重启数据不丢失;
+ **自增键隔离**:通过步长/偏移配置避免双写主键冲突。
- **GTID + AUTO_POSITION**:重启后自动定位同步位点,减少人工干预;
- **ROW 模式 binlog**:避免非确定性函数导致的数据不一致;
- **持久化数据卷**:独立 Volume 保障容器重启数据不丢失;
- **自增键隔离**:通过步长/偏移配置避免双写主键冲突。
## 1. 环境准备
### 1.1 节点信息(核心区分点)
| 节点 | 主机IP | server_id | auto_increment_offset | 核心标识 |
| :--- | :--- | :--- | :--- | :--- |
| 主节点A | ${NODE_A_IP} | 1 | 1 | 生成主键1、3、5… |
| 主节点B | ${NODE_B_IP} | 2 | 2 | 生成主键2、4、6… |
| 节点 | 主机IP | server_id | auto_increment_offset | 核心标识 |
| ---- | ------------ | --------- | --------------------- | ---------- |
| 主节点A | ${NODE_A_IP} | 1 | 1 | 生成主键1、3、5… |
| 主节点B | ${NODE_B_IP} | 2 | 2 | 生成主键2、4、6… |
### 1.2 系统依赖(两台主机统一执行)
```plain
# 安装 Docker & Docker Compose、MySQL 客户端
sudo apt update && sudo apt install -y docker.io docker-compose-plugin mysql-client
@@ -29,6 +35,7 @@ docker --version && docker compose version && mysql --version
```
### 1.3 目录规划(两台主机完全一致)
```plain
# 两台主机均执行以下命令,目录统一为 /data/mysql
sudo mkdir -p /data/mysql/{data,backup,logs}
@@ -36,7 +43,9 @@ sudo chown 999:999 /data/mysql -R # MySQL 容器默认UID/GID为999,避免权
```
## 2. 双主节点部署
### 2.1 Docker Compose 配置(两台主机完全一致)
创建 `/data/mysql/docker-compose.yml`,内容如下(无节点差异):
```plain
@@ -73,7 +82,9 @@ services:
```
### 2.2 MySQL 配置文件(my.cnf)
#### 节点A(${NODE_A_IP}):`/data/mysql/my.cnf`
```plain
[mysqld]
# ========== 节点唯一标识(核心区分点) ==========
@@ -120,6 +131,7 @@ super_read_only=OFF
```
#### 节点B(${NODE_B_IP}):`/data/mysql/my.cnf`
```plain
[mysqld]
# ========== 节点唯一标识(核心区分点) ==========
@@ -166,6 +178,7 @@ super_read_only=OFF
```
### 2.3 启动容器(两台主机统一执行)
```plain
# 进入目录并启动容器
cd /data/mysql && docker compose up -d
@@ -175,7 +188,9 @@ docker ps | grep mysql
```
## 3. 双主复制初始化
### 3.1 创建复制专用用户(两台主机统一执行)
```plain
# 无需区分节点,直接执行(创建repl用户,允许跨主机访问)
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
@@ -186,7 +201,9 @@ FLUSH PRIVILEGES;
```
### 3.2 配置双向复制(核心:仅IP参数不同)
#### 步骤1:节点A(${NODE_A_IP})配置为节点B的从库
```plain
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
STOP REPLICA;
@@ -198,13 +215,14 @@ CHANGE REPLICATION SOURCE TO
SOURCE_PASSWORD = 'afe123456',
SOURCE_AUTO_POSITION = 1, # GTID自动定位(无需手动找位点)
SOURCE_CONNECT_RETRY = 10,
SOURCE_RETRY_COUNT = 86400,
SOURCE_RETRY_COUNT = 9999999999,
GET_SOURCE_PUBLIC_KEY = 1; # 适配MySQL 8.0+密码认证
START REPLICA;
"
```
#### 步骤2:节点B(${NODE_B_IP})配置为节点A的从库
```plain
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
STOP REPLICA;
@@ -216,38 +234,44 @@ CHANGE REPLICATION SOURCE TO
SOURCE_PASSWORD = 'afe123456',
SOURCE_AUTO_POSITION = 1,
SOURCE_CONNECT_RETRY = 10,
SOURCE_RETRY_COUNT = 86400,
SOURCE_RETRY_COUNT = 9999999999,
GET_SOURCE_PUBLIC_KEY = 1;
START REPLICA;
"
```
## 4. 同步状态校验
### 4.1 核心校验命令(两台主机统一执行)
**A. Docker 执行模式 (包含 -h127.0.0.1):**
```bash
# 查看复制状态
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "SHOW REPLICA STATUS\G"
```
**B. 纯 SQL 模式:**
```sql
SHOW REPLICA STATUS\G
```
### 4.2 关键校验字段(必须全部满足)
| 字段 | 目标值 | 说明 |
| :--- | :--- | :--- |
| Replica_IO_Running | Yes | IO线程正常(接收binlog) |
| Replica_SQL_Running | Yes | SQL线程正常(执行事务) |
| Last_SQL_Error | 空 | 无同步错误 |
| Seconds_Behind_Source | 0 | 无同步延迟 |
| Retrieved_Gtid_Set | 非空 | 已获取对端节点GTID |
| Executed_Gtid_Set | 包含Retrieved_Gtid_Set | 已执行所有获取的事务 |
| 字段 | 目标值 | 说明 |
| --------------------- | -------------------- | ---------------- |
| Replica_IO_Running | Yes | IO线程正常(接收binlog) |
| Replica_SQL_Running | Yes | SQL线程正常(执行事务) |
| Last_SQL_Error | 空 | 无同步错误 |
| Seconds_Behind_Source | 0 | 无同步延迟 |
| Retrieved_Gtid_Set | 非空 | 已获取对端节点GTID |
| Executed_Gtid_Set | 包含Retrieved_Gtid_Set | 已执行所有获取的事务 |
### 4.3 数据一致性验证
```plain
# 节点A(${NODE_A_IP})创建测试数据
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
@@ -266,8 +290,11 @@ docker exec -it mysql mysql -uroot -pafe123456 -h${NODE_A_IP} -e "SELECT * FROM
```
## 5. 故障处理流程
### 5.1 宕机重启恢复
#### 场景:容器/主机重启后复制未自动恢复(两台主机操作逻辑一致,仅IP不同)
```plain
# 以节点A(${NODE_A_IP})为例,恢复与节点B的复制关系
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
@@ -289,7 +316,9 @@ SHOW REPLICA STATUS\G;
```
### 5.2 重建节点(单节点数据损坏/丢失)
#### 步骤1:从正常节点全量备份(假设节点B损坏,从节点A备份)
```plain
# 节点A(${NODE_A_IP})执行备份
docker exec -it mysql mysqldump -uroot -pafe123456 -h127.0.0.1 --all-databases --master-data=2 --single-transaction > /data/mysql/backup/full_backup.sql
@@ -299,6 +328,7 @@ scp /data/mysql/backup/full_backup.sql root@${NODE_B_IP}:/data/mysql/backup/
```
#### 步骤2:停止损坏节点并恢复数据(节点B执行)
```plain
# 停止mysql容器
cd /data/mysql && docker compose down
@@ -314,24 +344,34 @@ docker exec -i mysql mysql -uroot -pafe123456 < /data/mysql/backup/full_backup.s
```
#### 步骤3:重新配置双向复制
参考「3.2 配置双向复制」,重新执行节点B作为节点A从库、节点A作为节点B从库的配置命令(仅IP参数区分)。
### 5.3 复制冲突解决
详细的冲突定位与修复流程,请参考:[MySQL 复制冲突解决指南](./fault-analysis.md)
## 6. 日志管理
详细的日志轮转与安全登录配置,请参考:[MySQL 日志管理指南](./log-management.md)
## 7. 重要提醒
### 7.1 核心区分点(避免配置错误)
+ 两台主机仅 `server_id`、`report_host`(IP)、`auto_increment_offset` 三个参数不同,其余配置完全一致;
+ 容器名、目录路径、端口均统一为 `mysql`/`/data/mysql`/3306,通过主机IP区分节点。
- 两台主机仅 `server_id`、`report_host`(IP)、`auto_increment_offset` 三个参数不同,其余配置完全一致;
- 容器名、目录路径、端口均统一为 `mysql`/`/data/mysql`/3306,通过主机IP区分节点。
### 7.2 一致性限制
+ MySQL原生异步双主复制**无法保证严格的数据一致性**,双写场景仍可能出现冲突;
+ 生产环境建议**单写多读**(指定一个节点为写节点,另一个为读节点),避免双写冲突。
- MySQL原生异步双主复制**无法保证严格的数据一致性**,双写场景仍可能出现冲突;
- 生产环境建议**单写多读**(指定一个节点为写节点,另一个为读节点),避免双写冲突。
#### 总结
#### 跨主机双主复制的核心差异仅为 `server_id`、主机IP、自增偏移量,其余目录/容器名/配置可完全统一;
#### 同步故障优先通过错误日志定位冲突,修复数据而非跳过事务(避免永久不一致);
#### GTID模式下无需手动定位同步位点,重启/重建节点时仅需重新指定对端IP即可自动恢复复制。
@@ -150,9 +150,28 @@ scp /data/backup/mysql/20250127120000.7z root@192.168.1.100:/data/backup/mysql/
**注意**: 确保还原机的 `/data/backup/mysql/` 目录存在且有写入权限。
#### 步骤 3: 在还原机上执行还原
#### 步骤 3: 在还原机上还原前准备(清空数据并重启 MySQL)
在需要还原的 MySQL 服务器(从库)上执行还原脚本:
在需要还原的 MySQL 服务器(还原机)上,**先清空数据目录并重启容器**,再执行还原脚本,避免旧数据与备份冲突。
1. **删除数据目录中的现有数据**(在还原机执行):
```bash
# 删除 /data/mysql/data 下数据(请确认该路径为当前 MySQL 数据目录)
rm -rf /data/mysql/data/*
```
2. **在 docker-compose 目录下重启 MySQL 容器**(在还原机执行):
```bash
cd /data/docker-compose
docker-compose down mysql
docker-compose up -d mysql
```
等待 MySQL 启动就绪(可查看容器日志或稍等 10~30 秒)后,再进行步骤 4 的还原。
#### 步骤 4: 在还原机上执行还原脚本
在还原机上执行还原脚本:
```bash
cd /data/backup/mysql
@@ -171,50 +190,170 @@ cd /data/backup/mysql
- 导入备份数据(导入时禁用 binlog,避免循环复制)
- 设置 GTID purged(从备份时的 GTID 位置)
- 恢复 MySQL 为读写模式
- **自动启动复制并检查状态**
#### 步骤 4: 在备份机上启动同步(重要)
#### 步骤 5: 还原后创建账号(在还原机执行)
还原完成后,还原脚本会自动启动复制并显示同步状态。确认看到同步成功后,**需要在备份机(主库)上执行以下操作**:
还原完成后,在**还原机**上创建复制与业务所需账号(若备份中已含用户则可酌情跳过,建议按环境统一执行一次)。
**A. 创建复制账号 `repl` 与日志刷新账号 `log_flush`**
Docker 执行:
```bash
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
CREATE USER 'repl'@'%' IDENTIFIED BY 'afe123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
"
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
CREATE USER 'log_flush'@'127.0.0.1' IDENTIFIED BY 'afe123456';
GRANT RELOAD ON *.* TO 'log_flush'@'127.0.0.1';
FLUSH PRIVILEGES;
"
```
**B. 创建 G3SF 相关业务账号**
Docker 执行:
```bash
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
CREATE USER 'g3sf'@'%' IDENTIFIED BY 'k2-fkW@7z>zSYQo';
GRANT ALL PRIVILEGES ON *.* TO 'g3sf'@'%';
CREATE USER 'g3sfreader'@'%' IDENTIFIED BY '@feg3sf10port';
GRANT SELECT ON *.* TO 'g3sfreader'@'%';
CREATE USER 'g3sfsupport'@'%' IDENTIFIED BY '@feg3sf10port';
GRANT ALL PRIVILEGES ON *.* TO 'g3sfsupport'@'%';
FLUSH PRIVILEGES;
"
```
纯 SQL(在 MySQL 客户端中执行):
```sql
-- g3sf:应用库完全访问
CREATE USER 'g3sf'@'%' IDENTIFIED BY 'k2-fkW@7z>zSYQo';
GRANT ALL PRIVILEGES ON *.* TO 'g3sf'@'%';
-- g3sfreader:只读
CREATE USER 'g3sfreader'@'%' IDENTIFIED BY '@feg3sf10port';
GRANT SELECT ON *.* TO 'g3sfreader'@'%';
-- g3sfsupport:支持库完全访问
CREATE USER 'g3sfsupport'@'%' IDENTIFIED BY '@feg3sf10port';
GRANT ALL PRIVILEGES ON *.* TO 'g3sfsupport'@'%';
FLUSH PRIVILEGES;
```
#### 步骤 6: 在还原机上连接主 DB 并启动复制(在还原机执行)
在**还原机**上配置复制源为主库(将 `NODE_A_IP` 替换为实际主 DB 的 IP):
**A. Docker 执行模式 (包含 -h127.0.0.1):**
```bash
# 将 NODE_A_IP 替换为主 DB 的 IP
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'NODE_A_IP',
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'afe123456',
SOURCE_AUTO_POSITION = 1,
SOURCE_CONNECT_RETRY = 10,
SOURCE_RETRY_COUNT = 9999999999,
GET_SOURCE_PUBLIC_KEY = 1;
START REPLICA;
"
```
**B. 纯 SQL 模式:**
```sql
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'NODE_A_IP', -- 主 DB IP
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'afe123456',
SOURCE_AUTO_POSITION = 1,
SOURCE_CONNECT_RETRY = 10,
SOURCE_RETRY_COUNT = 9999999999,
GET_SOURCE_PUBLIC_KEY = 1;
START REPLICA;
```
等待 3 秒后,检查同步状态:
等待几秒后检查复制状态,确认 IO/SQL 均为 Yes:
**A. Docker 执行模式 (包含 -h127.0.0.1):**
```bash
sleep 3
sleep 5
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "SHOW REPLICA STATUS\G"
```
**B. 纯 SQL 模式:**
```sql
-- 等待 3 秒后执行
SHOW REPLICA STATUS\G;
```
检查关键指标:
- `Replica_IO_Running`: 应为 `Yes`
- `Replica_SQL_Running`: 应为 `Yes`
- `Last_IO_Error`: 应为空
- `Last_SQL_Error`: 应为空
- `Seconds_Behind_Source`: 延迟秒数(应逐渐减小)
- `Last_IO_Error` / `Last_SQL_Error`: 应为空
状态正常后,再进行步骤 7,在主库上配置指向本机(还原机/备份库)。
#### 步骤 7: 在主库上配置指向备份库(还原机)并检查状态(在主库执行)
在**主备份数据库(主库)**上配置复制源为当前还原机(备份库),将 `NODE_B_IP` 替换为还原机/备份 DB 的 IP:
**A. Docker 执行模式 (包含 -h127.0.0.1):**
```bash
# 将 NODE_B_IP 替换为备份 DB(还原机)的 IP
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'NODE_B_IP',
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'afe123456',
SOURCE_AUTO_POSITION = 1,
SOURCE_CONNECT_RETRY = 10,
SOURCE_RETRY_COUNT = 9999999999,
GET_SOURCE_PUBLIC_KEY = 1;
START REPLICA;
"
```
**B. 纯 SQL 模式:**
```sql
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'NODE_B_IP', -- 备份 DB(还原机)IP
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'afe123456',
SOURCE_AUTO_POSITION = 1,
SOURCE_CONNECT_RETRY = 10,
SOURCE_RETRY_COUNT = 9999999999,
GET_SOURCE_PUBLIC_KEY = 1;
START REPLICA;
```
等待几秒后再次检查主库复制状态:
```bash
sleep 5
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "SHOW REPLICA STATUS\G"
```
确认:
- `Replica_IO_Running`: 应为 `Yes`
- `Replica_SQL_Running`: 应为 `Yes`
- `Last_IO_Error` / `Last_SQL_Error`: 应为空
- `Seconds_Behind_Source`: 延迟应逐渐减小
至此,全量备份还原与主从(含主库侧)复制配置完成。
### 2.3 注意事项
1. **备份时机**: 建议在业务低峰期执行备份,减少对业务的影响
2. **网络传输**: 确保备份机和还原机之间网络畅通,备份文件较大时传输可能需要较长时间
3. **磁盘空间**: 确保还原机有足够的磁盘空间存放备份文件和临时解压文件
4. **权限要求**: 脚本需要 MySQL root 权限,以及 `/data/backup/mysql/` 目录的读写权限
3. **磁盘空间**: 确保还原机有足够的磁盘空间存放备份文件和临时解压文件;还原前清空 `/data/mysql/data` 前请确认该路径为当前 MySQL 数据目录
4. **权限要求**: 脚本需要 MySQL root 权限,以及 `/data/backup/mysql/`、`/data/mysql/data` 等目录的相应权限
5. **GTID 一致性**: 还原脚本会自动处理 GTID,确保复制能够正常继续
6. **备份机同步**: 还原完成后务必在备份机(主库)上执行 `START REPLICA` 并检查状态,确保双向复制正常
6. **还原前准备**: 还原前必须在还原机上删除 `/data/mysql/data` 数据并重启 MySQL 容器(步骤 3),再执行还原脚本,避免旧数据与备份冲突
7. **账号与复制顺序**: 还原后先创建账号(步骤 5),再在还原机配置指向主库的复制并检查状态(步骤 6),最后在主库上配置指向还原机的复制并检查状态(步骤 7),确保双向复制正常