适用于 ARM64 架构 Debian 13 (trixie) 环境 MySQL 8.0.41 Community Server (通用二进制安装)
一、部署环境
1.1 服务器信息
| 角色 | IP | 主机名 | 系统 | 架构 | MySQL版本 |
|---|---|---|---|---|---|
| 服务器A | 10.211.55.5 | Debian (trixie) | Debian 13 | aarch64 | 8.0.41 |
| 服务器B | 10.211.55.9 | Debian (trixie) | Debian 13 | aarch64 | 8.0.41 |
1.2 MySQL 安装过程回顾
由于 Oracle 官方从未为 ARM64 架构发布过 MySQL APT/RPM 包(所有 MySQL 版本的 APT 仓库仅支持 amd64 和 i386),本环境采用 通用二进制包(Generic Linux Tarball) 方式安装。
安装步骤摘要:
# 1. 下载 MySQL 8.0.41 ARM64 通用二进制包
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.41-linux-glibc2.28-aarch64.tar.xz
# 2. 解压到 /usr/local
tar xf mysql-8.0.41-linux-glibc2.28-aarch64.tar.xz -C /usr/local/
ln -sf /usr/local/mysql-8.0.41-linux-glibc2.28-aarch64 /usr/local/mysql
# 3. 安装系统依赖(ARM64 下 MySQL 8.0 仅缺 libnuma)
apt-get install -y libnuma1 libncurses6 libaio1t64
ln -sf /usr/lib/aarch64-linux-gnu/libaio.so.1t64 /usr/lib/aarch64-linux-gnu/libaio.so.1
# 4. 创建 mysql 用户和目录
groupadd -r mysql && useradd -r -g mysql -s /bin/false mysql
mkdir -p /var/lib/mysql /var/log/mysql /var/run/mysqld
chown -R mysql:mysql /var/lib/mysql /var/log/mysql /var/run/mysqld
# 5. 初始化 MySQL(--initialize-insecure 生成空 root 密码)
/usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql
# 6. 配置 systemd 服务
cat > /etc/systemd/system/mysql.service << 'EOF'
[Unit]
Description=MySQL Server
After=network.target
[Service]
Type=notify
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --datadir=/var/lib/mysql \
--socket=/var/run/mysqld/mysqld.sock --port=3306
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable mysql && systemctl start mysql
# 7. 配置 PATH
echo 'export PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh
当前配置基线(两台服务器相同):
# /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
port=3306
user=mysql
log-error=/var/log/mysql/error.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
两台服务器的 MySQL 目前是 独立运行 的,server_id 均为默认值 1,彼此无复制关系。本文档将在此基础上配置各种复制拓扑。
二、MYSQL 复制核心概念
2.1 什么是 MySQL 复制
MySQL 复制(Replication)是指将一台 MySQL 服务器(主库 / Master)上的数据变更,通过二进制日志(Binary Log)同步到另一台或多台服务器(从库 / Slave)上的过程。
2.2 复制原理(三步走)
主库 (Master) 从库 (Slave)
─────────── ───────────
① 数据变更写入 binlog ──推送──→ ② I/O 线程拉取 binlog 写入 relay log
③ SQL 线程回放 relay log 中的事件
-
Binary Log (binlog):主库记录所有数据修改事件的日志文件
-
I/O 线程:从库上运行的线程,负责从主库拉取 binlog 并写入 relay log
-
Relay Log:从库上暂存主库 binlog 事件的中转日志
-
SQL 线程:从库上运行的线程,负责读取 relay log 并在从库上执行
2.3 复制模式
| 模式 | binlog_format | 特点 |
|---|---|---|
| 基于语句 (SBR) | STATEMENT | 记录 SQL 语句本身,日志小但某些函数可能导致不一致 |
| 基于行 (RBR) | ROW | 记录每行数据的实际变更,一致性强但日志大(当前默认) |
| 混合模式 (MBR) | MIXED | 默认用 STATEMENT,必要时自动切换为 ROW |
2.4 复制方式
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 基于 binlog 位置 | 记录 binlog 文件名 + 偏移量 | 简单直接 | 切换主库时需手动计算位置 |
| 基于 GTID | 每个事务分配全局唯一 ID | 自动定位,故障切换简单 | 需要 GTID 模式开启 |
本文档两种方式都会介绍。
三、一主一从(MASTER-SLAVE)
┌──────────┐ binlog ┌──────────┐
│ Master │ ───────────────────────→ │ Slave │
│ .55.5 │ (只读副本) │ .55.9 │
│ 读写 │ │ 只读 │
└──────────┘ └──────────┘
概念: 最经典的复制拓扑。主库处理所有写操作,从库作为只读副本,用于数据备份、报表查询或读写分离中的”读”负载。MySQL 默认的异步复制就是这种模式。
3.1 基于 binlog 位置的配置方式
3.1.1 主库配置(10.211.55.5)
编辑 /etc/my.cnf,在 [mysqld] 段添加:
[mysqld]
# === 基础配置(已有) ===
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
port=3306
user=mysql
# === 复制相关配置(新增) ===
server-id = 1 # 服务器唯一 ID,主从必须不同
log_bin = /var/lib/mysql/binlog # 开启二进制日志(前缀,实际文件 binlog.000001)
binlog_format = ROW # 基于行的复制(推荐)
expire_logs_days = 7 # binlog 保留天数
max_binlog_size = 500M # 单个 binlog 文件最大大小
sync_binlog = 1 # 每次事务都同步 binlog 到磁盘(安全但略慢)
重启 MySQL:
systemctl restart mysql
创建复制专用账号:
-- 在主库上执行
CREATE USER 'repl'@'10.211.55.%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.211.55.%';
FLUSH PRIVILEGES;
-- 查看主库当前 binlog 位置(记下来,从库配置要用)
SHOW MASTER STATUS;
-- +---------------+----------+
-- | File | Position |
-- +---------------+----------+
-- | binlog.000001 | 857 |
-- +---------------+----------+
3.1.2 从库配置(10.211.55.9)
编辑 /etc/my.cnf,在 [mysqld] 段添加:
[mysqld]
# === 基础配置(已有) ===
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
port=3306
user=mysql
# === 复制相关配置(新增) ===
server-id = 2 # 必须与主库不同
relay_log = /var/lib/mysql/relay # 中继日志前缀
log_bin = /var/lib/mysql/binlog # 从库也开 binlog(便于以后提升为主库)
read_only = ON # 从库只读(root 和复制线程不受限)
重启 MySQL:
systemctl restart mysql
在从库上配置复制关系:
-- 在从库上执行
CHANGE MASTER TO
MASTER_HOST = '10.211.55.5',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_LOG_FILE = 'binlog.000001', -- 来自主库 SHOW MASTER STATUS 的 File
MASTER_LOG_POS = 857; -- 来自主库 SHOW MASTER STATUS 的 Position
-- 启动复制
START SLAVE;
-- 检查复制状态
SHOW SLAVE STATUS\G
关键指标:
Slave_IO_Running: Yes ← I/O 线程正常运行
Slave_SQL_Running: Yes ← SQL 线程正常运行
Seconds_Behind_Master: 0 ← 复制延迟(0 表示实时同步)
3.2 基于 GTID 的配置方式(推荐)
GTID (Global Transaction Identifier) 让每个事务有全局唯一编号,从库不需要手动指定 binlog 位置。
3.2.1 主库配置(10.211.55.5)
[mysqld]
server-id = 1
log_bin = /var/lib/mysql/binlog
binlog_format = ROW
# === GTID 配置 ===
gtid_mode = ON
enforce_gtid_consistency = ON
重启:
systemctl restart mysql
创建复制账号(同上):
CREATE USER 'repl'@'10.211.55.%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.211.55.%';
3.2.2 从库配置(10.211.55.9)
[mysqld]
server-id = 2
relay_log = /var/lib/mysql/relay
log_bin = /var/lib/mysql/binlog
read_only = ON
# === GTID 配置 ===
gtid_mode = ON
enforce_gtid_consistency = ON
重启后在从库执行:
-- GTID 方式不需要指定 binlog 文件和位置
CHANGE MASTER TO
MASTER_HOST = '10.211.55.5',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_AUTO_POSITION = 1; -- 自动定位,替代 MASTER_LOG_FILE + MASTER_LOG_POS
START SLAVE;
SHOW SLAVE STATUS\G
GTID 的优势: 切换主库时,只需 CHANGE MASTER TO MASTER_AUTO_POSITION=1,不用手动计算 binlog 偏移量。
3.3 验证复制
-- 在主库创建一个测试数据库
CREATE DATABASE test_repl;
USE test_repl;
CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO t1 VALUES (1, 'hello replication');
-- 在从库查询
USE test_repl;
SELECT * FROM t1;
-- +----+-------------------+
-- | id | name |
-- +----+-------------------+
-- | 1 | hello replication |
-- +----+-------------------+
四、主主复制(MASTER-MASTER)
┌──────────┐ ┌──────────┐
│ Master A │ ←────────→ │ Master B │
│ .55.5 │ 双向同步 │ .55.9 │
│ 读写 │ │ 读写 │
└──────────┘ └──────────┘
概念: 两台服务器互为主从,任意一台的写入都会同步到另一台。适合高可用场景(配合 Keepalived/ProxySQL 等),但需要处理 自增 ID 冲突 和 循环复制 问题。
4.1 配置步骤
两台服务器都需要同时作为主库和从库。
4.1.1 服务器 A(10.211.55.5)
[mysqld]
server-id = 1
log_bin = /var/lib/mysql/binlog
binlog_format = ROW
relay_log = /var/lib/mysql/relay
gtid_mode = ON
enforce_gtid_consistency = ON
# === 主主复制关键配置 ===
auto_increment_increment = 2 # 自增步长(服务器数量)
auto_increment_offset = 1 # 自增起始偏移(本机:1, 3, 5, 7...)
# 防止循环复制:本机的更新不再回写到本机
log_slave_updates = ON
4.1.2 服务器 B(10.211.55.9)
[mysqld]
server-id = 2
log_bin = /var/lib/mysql/binlog
binlog_format = ROW
relay_log = /var/lib/mysql/relay
gtid_mode = ON
enforce_gtid_consistency = ON
auto_increment_increment = 2
auto_increment_offset = 2
log_slave_updates = ON
4.1.3 创建复制账号(两台都要)
-- 在 10.211.55.5 上创建
CREATE USER 'repl'@'10.211.55.%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.211.55.%';
ALTER USER 'repl'@'10.211.55.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123456';
-- 在 10.211.55.9 上同样创建(如果之前一主一从已创建则跳过)
CREATE USER 'repl'@'10.211.55.%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.211.55.%';
ALTER USER 'repl'@'10.211.55.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123456';
4.1.4 建立双向复制
-- 在服务器 A (.55.5) 上执行:把 B 设为 A 的主库
CHANGE MASTER TO
MASTER_HOST = '10.211.55.9',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_AUTO_POSITION = 1;
START SLAVE;
-- 在服务器 B (.55.9) 上执行:把 A 设为 B 的主库
CHANGE MASTER TO
MASTER_HOST = '10.211.55.5',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_AUTO_POSITION = 1;
START SLAVE;
-- 两边都检查
SHOW SLAVE STATUS\G
# 10.211.55.9
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.211.55.9
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000002
Read_Master_Log_Pos: 758
Relay_Log_File: relay.000002
Relay_Log_Pos: 708
Relay_Master_Log_File: binlog.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 758
Relay_Log_Space: 908
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_UUID: 23786b26-57da-11f1-9fcf-001c420f4775
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 23786b26-57da-11f1-9fcf-001c420f4775:1
Executed_Gtid_Set: 01e7fb08-57da-11f1-ba69-001c429cec7c:1,
23786b26-57da-11f1-9fcf-001c420f4775:1
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.01 sec)
# 10.211.55.5
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.211.55.5
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000002
Read_Master_Log_Pos: 758
Relay_Log_File: relay.000002
Relay_Log_Pos: 708
Relay_Master_Log_File: binlog.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 758
Relay_Log_Space: 908
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 01e7fb08-57da-11f1-ba69-001c429cec7c
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 01e7fb08-57da-11f1-ba69-001c429cec7c:1
Executed_Gtid_Set: 01e7fb08-57da-11f1-ba69-001c429cec7c:1,
23786b26-57da-11f1-9fcf-001c420f4775:1
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
4.2 auto_increment 冲突解决原理
| 服务器 | offset | 生成的自增 ID |
|---|---|---|
| A (.55.5) | 1 | 1, 3, 5, 7, 9, 11… |
| B (.55.9) | 2 | 2, 4, 6, 8, 10, 12… |
两台同时插入数据时,自增 ID 永远不会冲突。
4.3 主主复制的黄金法则
-
始终使用 GTID —— 避免 binlog 位置混乱
-
不同表操作 —— 尽量让不同服务器操作不同表,减少冲突
-
避免同时更新同一行 —— 会导致复制中断
-
配合高可用中间件 —— ProxySQL、MySQL Router 等做读写分离和故障切换
五、常见问题与排查
5.1 复制中断
-- 查看错误信息
SHOW SLAVE STATUS\G
-- 关注这些字段:
-- Last_IO_Error: I/O 线程错误
-- Last_SQL_Error: SQL 线程错误
-- 常见中断原因及处理
-- 1. 主键冲突(最常见)
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; -- 跳过当前出错的事务
START SLAVE;
-- 2. GTID 模式下跳过事务
STOP SLAVE;
SET GTID_NEXT = 'aaa-bbb-ccc:5'; -- 要跳过的事务 GTID
BEGIN; COMMIT;
SET GTID_NEXT = AUTOMATIC;
START SLAVE;
-- 3. 使用 pt-slave-restart(Percona Toolkit)
pt-slave-restart --user=root --error-numbers=1062
5.2 延迟过大
-- 查看延迟
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: N ← 延迟 N 秒
-- 加速手段
-- 1. 开启并行复制
SET GLOBAL slave_parallel_workers = 8;
SET GLOBAL slave_parallel_type = LOGICAL_CLOCK;
-- 2. 临时跳过 binlog 写入(仅中间从库做级联时)
SET GLOBAL sync_binlog = 0;
-- 3. 检查是否有大事务或锁等待
SHOW PROCESSLIST;
SELECT * FROM information_schema.innodb_trx WHERE trx_state = 'RUNNING'\G
5.3 数据一致性检查
# 使用 Percona Toolkit 的 pt-table-checksum 检查主从数据是否一致
pt-table-checksum h=10.211.55.5,u=root --databases mydb
# 发现不一致时用 pt-table-sync 修复
pt-table-sync --sync-to-master h=10.211.55.9,u=root --databases mydb --print
5.4 常用监控命令
-- 查看所有从库状态
SHOW SLAVE STATUS\G
-- 查看复制过滤规则
SHOW SLAVE STATUS\G | grep -i replicate
-- 查看 binlog 事件
SHOW BINLOG EVENTS IN 'binlog.000001' LIMIT 10;
-- 查看 relay log 事件
SHOW RELAYLOG EVENTS IN 'relay.000001' LIMIT 10;
-- 查看当前所有连接
SHOW PROCESSLIST;
-- 查看复制线程状态
SELECT * FROM performance_schema.replication_applier_status_by_worker;
| 拓扑 | 复杂度 | 适用场景 | 关键配置 |
|---|---|---|---|
| 一主一从 | ⭐ | 备份、简单读写分离 | server-id, log_bin |
| 主主复制 | ⭐⭐⭐ | 高可用、双向同步 | auto_increment_offset/increment, GTID |
选型路线图
你的业务是?
│
┌────────────┼────────────┐
↓ ↓ ↓
只有两台机器 3台以上 多个独立业务库
│ │ │
↓ ↓ ↓
需要高可用? 读瓶颈大? 需要数据汇聚?
│
┌────┴────┐
↓ ↓
Yes No
│ │
↓ ↓
主主复制 一主一从
广告:














暂无评论内容