基于 CentOS 7.6 的 MySQL 8.0 主从复制

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

适用版本:CentOS 7(最小安装即可) 架构:1 主 + 1 从 特性:GTID + 半同步复制 + 自动备份 + 安全加固


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

1. 设置主机名

csharp 复制代码
 # 主库执行
 sudo hostnamectl set-hostname db-master
 ​
 # 从库执行
 sudo hostnamectl set-hostname db-slave

2. 配置时间同步

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

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

arduino 复制代码
 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

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

2. 安装 MySQL 官方 EL7 仓库

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

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

3. 安装 MySQL Server

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

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

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

解决方法

bash 复制代码
# 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

内容如下:

sql 复制代码
#!/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

bash 复制代码
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

复制代码
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

bash 复制代码
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

复制代码
sudo systemctl restart mysqld

4. 配置主从复制

查询插件是否安装

sql 复制代码
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; 之前

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

执行复制,

ini 复制代码
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. 验证复制状态

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

成功标志:

yaml 复制代码
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

bash 复制代码
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. 复制状态检查脚本(用于监控)

bash 复制代码
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

目录授权

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

2. 慢查询日志轮转

创建 /etc/logrotate.d/mysql

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

内容如下:

javascript 复制代码
/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

bash 复制代码
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"
bash 复制代码
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,授予完整常用开发权限组合,之前的用户均不能远程登录

sql 复制代码
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,让它帮你解决问题
相关推荐
源代码•宸25 分钟前
GoLang八股(Go语言基础)
开发语言·后端·golang·map·defer·recover·panic
czlczl2002092525 分钟前
OAuth 2.0 解析:后端开发者视角的原理与流程讲解
java·spring boot·后端
颜淡慕潇33 分钟前
Spring Boot 3.3.x、3.4.x、3.5.x 深度对比与演进分析
java·后端·架构
布列瑟农的星空33 分钟前
WebAssembly入门(一)——Emscripten
前端·后端
小突突突2 小时前
Spring框架中的单例bean是线程安全的吗?
java·后端·spring
iso少年2 小时前
Go 语言并发编程核心与用法
开发语言·后端·golang
掘金码甲哥2 小时前
云原生算力平台的架构解读
后端
码事漫谈2 小时前
智谱AI从清华实验室到“全球大模型第一股”的六年征程
后端
码事漫谈2 小时前
现代软件开发中常用架构的系统梳理与实践指南
后端
Mr.Entropy3 小时前
JdbcTemplate 性能好,但 Hibernate 生产力高。 如何选择?
java·后端·hibernate