基于 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,让它帮你解决问题
相关推荐
用户9718356334665 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪6 小时前
linux 拷贝文件或目录到指定的位置
linux
云技纵横6 小时前
Gap Lock 死锁实战:5 秒在本地复现 MySQL 间隙锁死锁
后端·mysql
无响应de神7 小时前
三、用户与权限管理
数据库·mysql
大树881 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush41 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5201 天前
Linux 11 动态监控指令top
linux
小宇宙Zz1 天前
Maven依赖冲突
java·服务器·maven