基于 CentOS 7.6 的 MySQL 8.0 主从复制

基于 CentOS 7 的完整、详细、可直接执行的 MySQL 8.0 主从复制部署流程

适用版本:CentOS 7(最小安装即可)

架构:1 主 + 1 从

特性:GTID + 半同步复制 + 自动备份 + 安全加固


第一步:基础环境准备(两台服务器均执行)

1. 设置主机名

bash 复制代码
# 主库执行
sudo hostnamectl set-hostname db-master

# 从库执行
sudo hostnamectl set-hostname db-slave

2. 配置时间同步

bash 复制代码
sudo timedatectl set-timezone Asia/Shanghai
sudo yum install -y chrony
sudo systemctl enable --now chronyd
timedatectl status  # 确认 "System clock synchronized: yes"

3. 关闭 SELinux(可选,避免权限问题)

bash 复制代码
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

4. 配置防火墙(可选,仅放行内网访问 3306)

创建脚本 setup_firewall.sh

bash 复制代码
#!/bin/bash
# setup_firewall.sh
INTERNAL_NET="10.0.0.0/16"  # 根据实际调整,覆盖主从 IP 段

sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-rich-rule="rule family=\"ipv4\" source address=\"${INTERNAL_NET}\" port protocol=\"tcp\" port=\"3306\" accept"
sudo firewall-cmd --reload
echo "防火墙已限制仅 ${INTERNAL_NET} 可访问 MySQL"

执行:

bash 复制代码
chmod +x setup_firewall.sh && sudo ./setup_firewall.sh

第二步:安装 MySQL 8.0(两台服务器均执行)

1. 卸载可能存在的 MariaDB

bash 复制代码
sudo yum remove -y mariadb-libs

2. 安装 MySQL 官方 EL7 仓库

bash 复制代码
sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-11.noarch.rpm

注意:必须是 el7,不是 el8!

3. 安装 MySQL Server

bash 复制代码
sudo yum install -y mysql-community-server

这里可能会存在安装失败的可能,原因是实际拉取是el8

复制代码
yum --assumeno install mysql-community-server | grep "Package.*will be installed"

解决方法

复制代码
# 1. 卸载可能存在的 el8 仓库
sudo rpm -e $(rpm -qa | grep mysql.*community.*release) 2>/dev/null

# 2. 重新安装 el7 仓库
sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-11.noarch.rpm

# 3. 强制锁定 baseurl 到 el7
sudo sed -i 's|baseurl=.*|baseurl=https://repo.mysql.com/yum/mysql-8.0-community/el/7/$basearch/|' /etc/yum.repos.d/mysql-community.repo

# 4. 清理缓存
sudo yum clean all && sudo rm -rf /var/cache/yum

# 5. 验证
yum info mysql-community-server | grep -E "Version|Release|From repo"
# 应显示 Release: 1.el7

4. 启动并设置开机自启

bash 复制代码
sudo systemctl enable --now mysqld

5. 获取临时 root 密码vvvv(主库重做,从库到这里)

bash 复制代码
TEMP_PASS=$(sudo grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}')
echo "临时密码: $TEMP_PASS"

第三步:安全初始化(两台服务器均执行)

创建脚本 secure_mysql.sh

复制代码
vi secure_mysql.sh

内容如下:

bash 复制代码
#!/bin/bash
ROOT_PASS="MySQLPass@2025!"
TEMP_PASS=$(sudo grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}')

mysql -u root -p"$TEMP_PASS" --connect-expired-password << EOF
ALTER USER 'root'@'localhost' IDENTIFIED BY '${ROOT_PASS}';
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
EOF

echo "安全初始化完成。root 密码: ${ROOT_PASS}"

执行:

bash 复制代码
chmod +x secure_mysql.sh && sudo ./secure_mysql.sh

第四步:主库配置(仅在 db-master 执行)

1. 创建慢日志目录

bash 复制代码
sudo mkdir -p /var/log/mysql
sudo chown mysql:mysql /var/log/mysql
sudo chmod 750 /var/log/mysql
sudo touch /var/log/mysql-slow.log
sudo chown mysql:mysql /var/log/mysql-slow.log
sudo chmod 640 /var/log/mysql-slow.log

2. 编辑 /etc/my.cnf

复制代码
vi /etc/my.cnf

内容如下:

ini 复制代码
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id=1

# Binlog
log-bin=mysql-bin
binlog_format=ROW
expire_logs_days=7
max_binlog_size=1G

# GTID
gtid_mode=ON
enforce_gtid_consistency=ON

# 半同步
plugin_load_add='rpl_semi_sync_master=semisync_master.so'
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000

# 日志
log_error=/var/log/mysqld.log
slow_query_log=ON
slow_query_log_file=/var/log/mysql-slow.log
long_query_time=1

# 安全
bind-address=0.0.0.0
skip_name_resolve=ON
symbolic-links=0

3. 重启 MySQL

bash 复制代码
sudo systemctl restart mysqld

4. 创建复制用户(注意从库 IP)

sql 复制代码
mysql -u root -p'MySQLPass@2025!' << EOF
-- 检查插件是否已加载
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM information_schema.PLUGINS 
WHERE PLUGIN_NAME = 'rpl_semi_sync_master';

-- 如果未安装,才执行 INSTALL(可选:跳过此步,直接启用)
-- INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

-- 直接启用即可(即使已安装,SET GLOBAL 不会报错)
SET GLOBAL rpl_semi_sync_master_enabled = 1;

-- 创建复制用户
CREATE USER IF NOT EXISTS 'repl'@'10.0.16.12' IDENTIFIED WITH mysql_native_password BY 'StrongReplPass2025!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.16.12';
FLUSH PRIVILEGES;
EOF

IP替换为你的从库真实 IP

第五步:从库配置(仅在 db-slave 执行)

1. 同样创建慢日志目录(同上)

bash 复制代码
sudo mkdir -p /var/log/mysql
sudo chown mysql:mysql /var/log/mysql
sudo chmod 750 /var/log/mysql
sudo touch /var/log/mysql-slow.log
sudo chown mysql:mysql /var/log/mysql-slow.log
sudo chmod 640 /var/log/mysql-slow.log

2. 编辑 /etc/my.cnf

复制代码
vi /etc/my.cnf

内容如下:

ini 复制代码
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id=2

gtid_mode=ON
enforce_gtid_consistency=ON
read_only=ON

plugin_load_add='rpl_semi_sync_slave=semisync_slave.so'
rpl_semi_sync_slave_enabled=1

log_error=/var/log/mysqld.log
slow_query_log=ON
slow_query_log_file=/var/log/mysql-slow.log
long_query_time=1

bind-address = 0.0.0.0
skip_name_resolve=ON
symbolic-links=0

3. 重启 MySQL

bash 复制代码
sudo systemctl restart mysqld

4. 配置主从复制

查询插件是否安装

复制代码
mysql -u root -p'MySQLPass@2025!' << EOF
SELECT PLUGIN_NAME, PLUGIN_STATUS 
FROM information_schema.PLUGINS 
WHERE PLUGIN_NAME = 'rpl_semi_sync_slave';
EOF

观察查询出来的状态是否为ACTIVE,如果不是需要在下面的命令中添加 INSTALL,放在 SET GLOBAL rpl_semi_sync_slave_enabled = 1; 之前

复制代码
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

执行复制,

sql 复制代码
mysql -u root -p'MySQLPass@2025!' << EOF
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
STOP SLAVE;
CHANGE MASTER TO
  MASTER_HOST='10.0.4.16',
  MASTER_USER='repl',
  MASTER_PASSWORD='StrongReplPass2025!',
  MASTER_AUTO_POSITION=1;
START SLAVE;
EOF

IP替换成主库IP

密码换成上面复制用户设置的密码

查询部分,可以不要,图中命令错了,以上面的文字命令为准

5. 验证复制状态

bash 复制代码
mysql -u root -p'MySQLPass@2025!' -e "SHOW SLAVE STATUS\G" | grep -E "IO_Running|SQL_Running|Seconds_Behind_Master"

成功标志:

复制代码
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0

第六步:配置自动备份(仅主库执行)

1. 创建备份用户

sql 复制代码
mysql -u root -p'MySQLPass@2025!' << EOF
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'BackupPass2025!';
GRANT SELECT, RELOAD, SHOW DATABASES, LOCK TABLES, REPLICATION CLIENT, PROCESS ON *.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;
EOF

2. 创建备份脚本 /opt/scripts/mysql_backup.sh

复制代码
vi scripts/mysql_backup.sh

内容如下:

bash 复制代码
#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M)
LOG_FILE="/var/log/mysql_backup.log"

mkdir -p "$BACKUP_DIR"

/usr/bin/mysqldump \
  --user=backup \
  --password='BackupPass2025!' \
  --single-transaction \
  --master-data=2 \
  --set-gtid-purged=ON \
  --routines --triggers --all-databases --hex-blob \
  > "${BACKUP_DIR}/mysql_full_${DATE}.sql" 2>> "$LOG_FILE"

if [ $? -eq 0 ]; then
  gzip "${BACKUP_DIR}/mysql_full_${DATE}.sql"
  find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete
  echo "[$(date)] 备份成功" >> "$LOG_FILE"
else
  echo "[$(date)] 备份失败" >> "$LOG_FILE"
  exit 1
fi

3. 设置定时任务

bash 复制代码
sudo mkdir -p /opt/scripts
sudo cp mysql_backup.sh /opt/scripts/
sudo chmod +x /opt/scripts/mysql_backup.sh

echo "0 2 * * * root /opt/scripts/mysql_backup.sh" | sudo tee /etc/cron.d/mysql-backup

这里我是先创建脚本目录后,再写的脚本,所以这里就没有复制这个步骤

第七步:监控与日志轮转(从库执行)

1. 复制状态检查脚本(用于监控)

复制代码
vi /usr/local/bin/check_replication.sh

内容如下:

bash 复制代码
# /usr/local/bin/check_replication.sh
MYSQL_PASS="MySQLPass@2025!"
IO=$(mysql -u root -p"$MYSQL_PASS" -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Slave_IO_Running:" | awk '{print $2}')
SQL=$(mysql -u root -p"$MYSQL_PASS" -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Slave_SQL_Running:" | awk '{print $2}')
DELAY=$(mysql -u root -p"$MYSQL_PASS" -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Seconds_Behind_Master:" | awk '{print $2}')

if [[ "$IO" == "Yes" && "$SQL" == "Yes" && "$DELAY" != "NULL" ]]; then
  echo "replication_ok 1"
  echo "seconds_behind $DELAY"
else
  echo "replication_ok 0"
fi

目录授权

复制代码
sudo chmod +x /usr/local/bin/check_replication.sh

2. 慢查询日志轮转

创建 /etc/logrotate.d/mysql

复制代码
vi /etc/logrotate.d/mysql

内容如下:

conf 复制代码
/var/log/mysql-slow.log {
    daily
    missingok
    rotate 60
    compress
    delaycompress
    notifempty
    create 640 mysql mysql
    postrotate
        /usr/bin/mysql -u root -p'MySQLPass@2025!' -e 'SELECT 1;' > /dev/null 2>&1 || true
    endscript
}

第八步:手动高可用切换预案(从库执行)

创建 /opt/scripts/promote_to_master.sh

复制代码
sudo mkdir -p /opt/scripts
vi /opt/scripts/promote_to_master.sh

内容如下:

bash 复制代码
#!/bin/bash
MYSQL_PASS="MySQLPass@2025!"

mysql -u root -p"$MYSQL_PASS" << EOF
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only = OFF;
EOF

# 可选:更新 server-id(避免未来冲突)
sudo sed -i 's/server-id=2/server-id=1/' /etc/my.cnf
sudo systemctl restart mysqld

NEW_IP=$(ip route get 1 | awk '{print $7; exit}')
echo "已提升为新主库!请将应用写地址切换至 $NEW_IP"
复制代码
sudo chmod +x /opt/scripts/promote_to_master.sh

原主库恢复后:清空 /var/lib/mysql,重新初始化或从备份恢复,再配置为新从库。


检查清单

项目 状态
主从 GTID 复制正常 SHOW SLAVE STATUS
半同步插件加载成功 SHOW PLUGINS LIKE '%semi%'
防火墙仅限内网 firewall-cmd --list-all
root 无法远程登录 SELECT host,user FROM mysql.user;
每日备份可执行 检查 /backup/mysql/
慢日志权限正确 ls -l /var/log/mysql-slow.log
时间同步正常 chronyc sources -v

远程连接(主库执行,从库会自动复制)

创建专属远程连接的用户catgod007,授予完整常用开发权限组合,之前的用户均不能远程登录

复制代码
CREATE USER 'catgod007'@'%' IDENTIFIED BY 'StrongAdminPass@2025!';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER,INDEX ON *.* TO 'catgod007'@'%';
FLUSH PRIVILEGES;

权限说明

权限 能做什么 典型场景
SELECT 查数据 查询用户信息
INSERT 插入新记录 注册新用户
UPDATE 修改记录 更新资料
DELETE 删除记录 删除订单
CREATE 建库/建表 初始化 schema
DROP 删库/删表 清理测试数据
ALTER 改表结构 加新字段
INDEX 建/删索引 优化查询性能

菜鸡说

  • 从库执行同步后,后续写相关的命令直接写在主库,从库用于查看即可,否则会造成你将命令在主从库都执行后,从库同步时会发生冲突导致从库无法复制主库。
  • 遇到问题问AI,解决问题的速度,比你去找各种解决方式要快得多,前提是你描述问题比较细致,像我这篇文章,遇到问题,你直接发给AI,让它帮你解决问题
相关推荐
LiYingL2 小时前
AlignGuard-LoRA:一种结合了高效微调和安全保护的新正则化方法
服务器·安全
笨蛋少年派2 小时前
Maxwell数据变更捕获工具简介
数据库·mysql
春日见2 小时前
如何跑通,吃透一个开源项目?
linux·运维·开发语言·数码相机·matlab
Blueeyedboy5212 小时前
服务器监控工具-netdata
运维·服务器
邂逅星河浪漫2 小时前
【MySQL 事务】详细介绍+实例
数据库·mysql·事务
TG:@yunlaoda360 云老大2 小时前
华为云国际站代理商DSS的跨区域备份与恢复具体是如何实现的?
运维·服务器·华为云
Ccjf酷儿2 小时前
计算机网络 (郑烇) 2 应用层
运维·服务器·计算机网络
寰天柚子2 小时前
服务器性能优化实战:从资源瓶颈定位到极致调优(附租赁服务器适配指南)
运维·服务器·udp
用户6135411460162 小时前
【麒麟Kylin】cmake-3.16.5 rpm包安装步骤详解 附常见问题
linux