news 2026/4/21 16:11:20

MySQL / MariaDB 主从复制架构实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL / MariaDB 主从复制架构实战指南

在生产环境中,数据库单点故障是最大的噩梦之一。本文将从最基础的 MariaDB 主从复制出发,逐步演进到 MySQL 双主同步,最终搭建一套基于 Keepalived + 双主架构的完整高可用方案。所有配置均来自生产环境实战验证,可直接落地使用。

环境说明:

角色主机名IP数据库
Masterrhel-efserver192.168.1.25MariaDB / MySQL
Slave / Backuprhel-efserver-bak192.168.1.28MariaDB / MySQL
VIP192.168.1.100Keepalived 虚拟漂移 IP

一、MariaDB 主从复制

MariaDB 是 MySQL 的分支,复制原理完全一致:Master 将数据变更写入二进制日志(Binlog),Slave 通过 I/O 线程读取 Binlog 写入中继日志(Relay Log),再由 SQL 线程重放完成同步。

1. Master 节点配置

编辑 MariaDB 服务配置文件,开启 Binlog 并设置唯一的server-id

# nano /etc/my.cnf.d/mariadb-server.cnf [mysqld] server-id = 1 log_bin = mysql-bin binlog_ignore_db = mysql

参数说明:

  • server-id:集群内每台节点必须唯一,建议使用 IP 尾数或递增数字。
  • log_bin:启用二进制日志,文件名前缀为mysql-bin
  • binlog_ignore_db:忽略 mysql 系统库的同步,减少不必要的日志量。

修改完成后重启 MariaDB 服务。

2. 创建复制账号

在 Master 上创建专用的复制用户,仅授予最小权限:

-- 创建用户 repl,允许从 rhel-efserver-bak 连接 GRANT REPLICATION SLAVE ON *.* TO 'repl'@'rhel-efserver-bak' IDENTIFIED BY 'Ins@1234';

3. 记录 Master 状态

MariaDB [(none)]> SHOW MASTER STATUS; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 655 | | mysql | +------------------+----------+--------------+------------------+

提示:记下FilePosition的值,Slave 连接时需要用到。

4. Slave 节点配置

# nano /etc/my.cnf.d/mariadb-server.cnf [mysqld] server-id = 2 log_bin = mysql-bin binlog_ignore_db = mysql

5. 配置并启动复制

指定 Master 的连接信息并启动同步进程:

CHANGE MASTER TO MASTER_HOST='rhel-efserver', MASTER_USER='repl', MASTER_PASSWORD='Ins@1234'; MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=655; START SLAVE;

6. 验证复制状态

# 查询状态 show slave status\G; MariaDB [(none)]> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: rhel-efserver Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 655 Relay_Log_File: mariadb-relay-bin.000002 Relay_Log_Pos: 954 Relay_Master_Log_File: mysql-bin.000001 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: 655 Relay_Log_Space: 1265 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_SSL_Crl: Master_SSL_Crlpath: Using_Gtid: No Gtid_IO_Pos: Replicate_Do_Domain_Ids: Replicate_Ignore_Domain_Ids: Parallel_Mode: conservative SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Slave_DDL_Groups: 2 Slave_Non_Transactional_Groups: 0 Slave_Transactional_Groups: 0 1 row inset (0.000 sec)

重点关注以下两个指标,均为Yes即表示复制正常运行:

Slave_IO_Running: Yes ← I/O 线程已连接 Master,正常读取 Binlog Slave_SQL_Running: Yes ← SQL 线程正常运行,正在重放中继日志 Seconds_Behind_Master: 0 ← 从库延迟秒数,0 表示完全同步

二、MySQL 主从复制

MySQL 8.x 的主从配置与 MariaDB 基本相同,主要区别在于用户认证方式的变化。以下是核心步骤:

1. 全量数据导出(主库执行)

使用--single-transaction参数保证 InnoDB 数据的一致性快照:

mysqldump -uroot -pIns@1234 --single-transaction --all-databases > /var/lib/mysql/efab.sql

2. 创建复制用户

CREATE USER 'repl'@'%' IDENTIFIED BY 'Ins@1234'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;

提示:生产环境中建议使用mysql_native_password认证插件以兼容旧客户端,或配置 SSL 加密复制通道。

3. 从库导入数据

将主库的全量备份导入从库:

mysql -uroot -p < /var/lib/mysql/efab-bak.sql

4. 启动复制

CHANGE MASTER TO MASTER_HOST='rhel-efserver', MASTER_USER='repl', MASTER_PASSWORD='Ins@1234', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=655; START SLAVE;

三、双主(Master-Master)架构

传统主从架构中,Slave 只能读不能写,Master 故障时需要手动切换。双主架构让两台节点互为 Master,各自承担写操作,配合 Keepalived 实现自动故障转移,才是真正的生产级高可用。

1. 架构示意

192.168.1.100 (VIP) │ ┌──────────┴──────────┐ ▼ ▼ ┌─────────┐ ┌─────────┐ │ Master A│◄──────► │ Master B│ │ .25 │ 互为主从 │ .28 │ └─────────┘ └─────────┘ │ │ read_only=0 read_only=1 (当前可写) (当前只读) │ │ ┌──┴─────────────────────┴──┐ │ Keepalived 自动切换 │ └───────────────────────────┘

2. Master A 配置(192.168.1.25)

[mysqld] # --- 基本设置 --- server-id = 25 # 必须唯一,建议用IP尾数 port = 3306 datadir = /var/lib/mysql socket = /var/lib/mysql/mysql.sock # --- 复制核心配置 --- log-bin = mysql-bin # 启用二进制日志 binlog-ignore-db = mysql binlog_format = row # 推荐使用 ROW 格式,数据最安全 relay-log = relay-bin log_slave_updates = 1 # 关键:从库执行完同步后也记入自己的binlog # --- 防止主键冲突 (双主必备) --- auto_increment_increment = 2 # 步长为2 auto_increment_offset = 1 # 初始值为1 (生成 ID 为 1, 3, 5...) # --- 高可用与安全设置 --- read_only = 0 # 主库初始为可读写 skip_name_resolve = 1 # 禁用DNS解析,提高连接速度 innodb_flush_log_at_trx_commit = 1 sync_binlog = 1

核心参数解析:

  • log_slave_updates = 1:双主架构的关键!没有它,A 的变更通过复制到 B 后不会写入 B 的 Binlog,无法再同步回 A。
  • auto_increment_increment = 2+auto_increment_offset:两台节点分别生成奇数 ID(1, 3, 5…)和偶数 ID(2, 4, 6…),从根本上避免自增主键冲突。

3. Master B 配置(192.168.1.28)

[mysqld] # --- 基本设置 --- server-id = 28 # 必须唯一 port = 3306 datadir = /var/lib/mysql socket = /var/lib/mysql/mysql.sock # --- 复制核心配置 --- log-bin = mysql-bin binlog-ignore-db = mysql binlog_format = row relay-log = relay-bin log_slave_updates = 1 # 关键:允许数据级联同步 # --- 防止主键冲突 (双主必备) --- auto_increment_increment = 2 # 步长为2 auto_increment_offset = 2 # 初始值为2 (生成 ID 为 2, 4, 6...) # --- 高可用与安全设置 --- read_only = 1 # 备库初始设为只读,由 Keepalived 脚本控制开关 skip_name_resolve = 1 innodb_flush_log_at_trx_commit = 1 sync_binlog = 1

4. 建立互为主从关系

Step 1:在两台节点分别创建复制用户(以 1.25 为例,1.28 同理):

-- 在 192.168.1.25 上执行 CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'Ins@1234'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

Step 2:互相指定对方为 Master 并启动复制:

-- 在 192.168.1.28 上执行:指定 1.25 为自己的 Master CHANGE MASTER TO MASTER_HOST='192.168.1.25', MASTER_USER='repl', MASTER_PASSWORD='Ins@1234'; START SLAVE; -- 在 192.168.1.25 上执行:指定 1.28 为自己的 Master CHANGE MASTER TO MASTER_HOST='192.168.1.28', MASTER_USER='repl', MASTER_PASSWORD='Ins@1234'; START SLAVE;

5. 验证双主状态

在两台节点上分别执行SHOW SLAVE STATUS\G,确认Slave_IO_RunningSlave_SQL_Running均为Yes


四、Keepalived 自动故障转移

光有双主还不够——应用需要通过一个固定的 VIP 访问数据库,主节点挂掉时 VIP 自动漂移到备节点。这就是 Keepalived 的职责。

1. 故障切换脚本

to_master.sh:节点升为 Master 时执行:检查同步延迟,延迟合格后解除只读,接管写操作。

#!/bin/bash # --- 配置项 --- MYSQL_USER="root" MYSQL_PASS="Ins@1234" MYSQL_CONN="mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e" MAX_DELAY=5 # 允许的最大主从延迟秒数 echo"$(date) [INFO]: Keepalived 状态切换为 MASTER,正在检查同步状态..." >> /var/log/keepalived_mysql.log # 1. 检查 MySQL 服务是否存活 if ! mysqladmin -u${MYSQL_USER} -p${MYSQL_PASS} ping > /dev/null 2>&1; then echo"$(date) [ERROR]: MySQL 服务未运行,无法接管!" >> /var/log/keepalived_mysql.log exit 1 fi # 2. 等待数据同步完成(针对双主架构恢复后的数据补齐) RETRY=0 while [ $RETRY -lt 10 ]; do DELAY=$($MYSQL_CONN"SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master" | awk '{print $2}') if [[ "$DELAY" == "NULL" ]] || [[ -z "$DELAY" ]]; then echo"$(date) [WARN]: Slave 状态异常或未连接,请检查主从复制状态。" >> /var/log/keepalived_mysql.log break elif [ "$DELAY" -le $MAX_DELAY ]; then echo"$(date) [INFO]: 数据同步完成 (延迟: ${DELAY}s),准备开启读写。" >> /var/log/keepalived_mysql.log break else echo"$(date) [INFO]: 等待同步中,当前延迟: ${DELAY}s..." >> /var/log/keepalived_mysql.log sleep 2 let RETRY++ fi done # 3. 解除只读状态,正式接管业务 $MYSQL_CONN"SET GLOBAL read_only = 0; SET GLOBAL super_read_only = 0;" if [ $? -eq 0 ]; then echo"$(date) [SUCCESS]: 成功切换为读写模式 (Master)。" >> /var/log/keepalived_mysql.log else echo"$(date) [ERROR]: 切换读写模式失败!" >> /var/log/keepalived_mysql.log exit 1 fi

to_backup.sh:节点降为 Backup 时执行:立即开启只读,防止脑裂写入。

#!/bin/bash MYSQL_USER="root" MYSQL_PASS="Ins@1234" echo "$(date) [INFO]: Keepalived 状态切换为 BACKUP,开启只读模式。" >> /var/log/keepalived_mysql.log mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "SET GLOBAL read_only = 1; SET GLOBAL super_read_only = 1;"

安全机制:super_read_only连拥有 SUPER 权限的用户也只能读了,彻底杜绝脑裂写入的可能。

2. Keepalived 配置

Master 节点(192.168.1.25):

global_defs { router_id m01 vrrp_skip_check_adv_addr # vrrp_strict # 注释掉,否则在某些网络环境下VIP无法ping通 vrrp_garp_interval 0 vrrp_gna_interval 0 } # 脚本1:检查 Nginx 和 Broker 服务 vrrp_script check_services { script "pidof nginx && systemctl is-active dcv-session-manager-broker" interval 2 weight -20 # 失败则权重减 20 } # 脚本2:检查 MySQL 服务状态 vrrp_script check_mysql { script "mysqladmin ping -u root -p'Ins@1234'" interval 2 weight -30 # 失败则权重减 30 } vrrp_instance VI_1 { state MASTER # 主节点初始状态 interface eth2 # 请确认网卡名称正确(如 ens33, eth0 等) virtual_router_id 51 # 主备必须一致 priority 100 # 主节点优先级(需高于备节点) advert_int 1 authentication { auth_type PASS auth_pass dcv_ha_pwd } virtual_ipaddress { 192.168.1.100 # 虚拟IP (VIP) } track_script { check_services check_mysql } # 状态切换触发脚本 notify_master "/etc/keepalived/to_master.sh"# 变为MASTER时:关闭只读,开启写 notify_backup "/etc/keepalived/to_backup.sh"# 变为BACKUP时:开启只读 notify_fault "/etc/keepalived/to_backup.sh"# 发生故障时:强制只读 }

Backup 节点(192.168.1.28):

global_defs { router_id m02 # 建议与主节点不同 vrrp_skip_check_adv_addr # vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_script check_services { script "pidof nginx && systemctl is-active dcv-session-manager-broker" interval 2 weight -20 } vrrp_script check_mysql { script "mysqladmin ping -u root -p'Ins@1234'" interval 2 weight -30 } vrrp_instance VI_1 { state BACKUP # 备节点初始状态 interface eth2 # 必须与物理网卡一致 virtual_router_id 51 priority 90 # 优先级低于主节点 advert_int 1 authentication { auth_type PASS auth_pass dcv_ha_pwd } virtual_ipaddress { 192.168.1.100 } track_script { check_services check_mysql } # 状态切换触发脚本 notify_master "/etc/keepalived/to_master.sh" notify_backup "/etc/keepalived/to_backup.sh" notify_fault "/etc/keepalived/to_backup.sh" }

3. 故障转移流程

┌─────────────────────────────────────────────────────┐ │ 正常状态 │ │ Master A (.25) ←── VIP ──→ Backup B (.28) │ │ read_only=0 (读写) read_only=1 (只读) │ └─────────────────────────────────────────────────────┘ │ Master A 故障 ▼ ┌────────────────────────────────────────────────────┐ │ 故障转移 │ │ 1. check_mysql 检测失败,priority 100-30 = 70 │ │ 2. Backup B priority(90) > 70,接管 VIP │ │ 3. 触发 to_master.sh:检查延迟 → 解除只读 │ │ 4. 触发 to_backup.sh(A 恢复后):开启只读 │ └─────────────────────────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────┐ │ 恢复后状态 │ │ Old Master (.25) New Master (.28) ←── VIP │ │ read_only=1 (只读) read_only=0 (读写) │ └─────────────────────────────────────────────────────┘

五、用户管理与认证

生产环境中,MySQL 8.x 默认使用caching_sha2_password认证,如果应用驱动不兼容,需要手动切换认证方式:

-- 修改现有用户的认证插件为 mysql_native_password ALTER USER 'dcvbk'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Ins@1234'; -- 创建新用户并授权 CREATE USER 'dcvbk'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Ins@1234'; GRANT ALL PRIVILEGES ON dcvdb.* TO 'dcvbk'@'localhost'; -- 验证用户信息 SELECT user, host, plugin FROM mysql.user WHERE user = 'dcvbk'; SHOW GRANTS FOR 'dcvtest'@'%';

六、总结

本文覆盖了 MySQL / MariaDB 复制架构从入门到生产的完整路径:

方案适用场景优势不足
MariaDB 主从读写分离、报表查询配置简单,上手快手动故障切换
MySQL 主从数据备份、读扩展8.x 原生支持 GTID手动故障切换
双主 + Keepalived生产级高可用自动故障转移,零停机架构复杂度更高

生产部署建议:

  • 网络层面:主备节点部署在同一机房、同网段,尽量降低网络延迟
  • 监控告警:务必监控Seconds_Behind_MasterSlave_IO_RunningSlave_SQL_Running三个指标
  • 定期演练:每季度至少一次手动故障切换演练,确保预案有效
  • 数据校验:使用pt-table-checksum/pt-table-sync(Percona Toolkit)定期校验主备数据一致性
  • 备份兜底:主从复制不是备份方案!仍需配合定期全量备份 + Binlog 增量备份

最后提醒:没有银弹——双主架构解决了单点故障,但引入了脑裂和数据一致性的新挑战。根据业务对 RPO / RTO 的要求,选择最适合的方案,而不是最复杂的方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 16:10:17

从OpenPCDet到ROS:PointPillars实时3D检测的部署与调优实践

1. 从实验室到机器人&#xff1a;PointPillars的落地挑战 第一次把PointPillars模型部署到ROS时&#xff0c;我看着屏幕上跳动的检测框延迟超过2秒&#xff0c;差点以为自己在看PPT播放。这可能是很多算法工程师转向实际部署时遇到的典型场景——实验室里mAP高达80%的模型&…

作者头像 李华
网站建设 2026/4/21 16:08:36

IK分词器进阶:自定义词典与智能模式在Java项目中的实战应用

1. 为什么需要自定义词典&#xff1f; 在实际项目中&#xff0c;我们经常会遇到一些特殊词汇&#xff0c;比如电商领域的"iPhone 12 Pro Max"、医疗行业的"冠状动脉粥样硬化性心脏病"&#xff0c;这些词汇如果直接用默认词典进行分词&#xff0c;结果往往不…

作者头像 李华
网站建设 2026/4/21 16:08:25

3分钟掌握B站缓存视频转换:m4s转MP4的终极解决方案

3分钟掌握B站缓存视频转换&#xff1a;m4s转MP4的终极解决方案 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾经在B站收藏了珍贵的视频…

作者头像 李华
网站建设 2026/4/21 16:07:20

低成本RS-485通信方案:用STC15+SP3485改造老旧设备(含自动收发电路详解)

STC15SP3485工业级RS-485改造实战&#xff1a;零代码实现自动收发通信 在工业自动化设备升级和智能家居中控系统改造中&#xff0c;RS-485通信因其抗干扰能力强、传输距离远等优势成为首选方案。但传统改造方式往往面临单片机资源占用高、软件复杂度大等痛点。本文将揭秘如何利…

作者头像 李华