说明:
my.cnf是 MySQL 的 "总开关 + 总设置"
本流程完全基于你实际遇到的问题优化(含 socket 路径、服务崩溃、UUID 重复、数据不一致、中文支持等所有坑的解决方案),小白可直接复制命令执行,全程无冗余步骤。
一、环境说明
| 角色 | 服务器 IP | 系统版本 | MySQL 版本 | 核心密码(统一设置,避免混淆) |
|---|---|---|---|---|
| 主库(Master) | 192.168.200.100 | CentOS7 | 5.7.x | MySQL 登录密码:Mysql123!;复制用户密码:Repl123@ |
| 从库(Slave) | 192.168.200.101 | CentOS7 | 5.7.x | MySQL 登录密码:Mysql123!;复制用户密码:Repl123@ |
二、前置准备(主库 + 从库都要执行)
1. 关闭防火墙和 SELINUX(避免端口拦截)
# 关闭防火墙(永久生效)
systemctl stop firewalld
systemctl disable firewalld
# 关闭SELINUX(临时+永久)
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
2. 安装 MySQL5.7 并解决启动 / 连接问题
# 安装依赖
yum install -y libaio-devel wget
# 下载并安装MySQL yum源
wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
rpm -ivh mysql57-community-release-el7-11.noarch.rpm
yum install -y mysql-community-server
# 创建数据目录并授权(避免权限报错)
mkdir -p /data/mysql /var/lib/mysql
chown -R mysql:mysql /data/mysql /var/lib/mysql
chmod -R 755 /data/mysql /var/lib/mysql
# 初始化MySQL(生成临时密码)
mysqld --initialize --user=mysql --datadir=/data/mysql
# 替换systemd启动脚本(解决启动后崩溃问题)
cat > /usr/lib/systemd/system/mysqld.service << EOF
[Unit]
Description=MySQL Server
After=network.target
[Service]
User=mysql
Group=mysql
ExecStart=/usr/sbin/mysqld --defaults-file=/etc/my.cnf
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 重新加载配置并启动MySQL
systemctl daemon-reload
systemctl start mysqld
systemctl enable mysqld
# 解决socket路径不匹配问题(一劳永逸)
ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock
# 查看临时密码并修改为永久密码(Mysql123!)
temp_pwd=$(grep "temporary password" /data/mysql/localhost.localdomain.err | awk '{print $NF}')
mysql -uroot -p"$temp_pwd" --socket=/var/lib/mysql/mysql.sock -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'Mysql123!';"
# 验证登录(成功进入mysql>即为正常)
mysql -uroot -pMysql123!
三、主库(192.168.200.100)配置
1. 修改主库配置文件(开启 binlog + 字符集)
cat > /etc/my.cnf << EOF
[mysqld]
server-id=1 # 主库唯一ID,不可与从库重复
log-bin=mysql-bin # 开启二进制日志(主从核心)
datadir=/data/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/data/mysql/localhost.localdomain.err
pid-file=/data/mysql/localhost.localdomain.pid
binlog-ignore-db=mysql # 忽略同步系统库
binlog-ignore-db=information_schema
# 中文支持配置
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
EOF
# 重启主库使配置生效
systemctl restart mysqld
2. 创建复制用户并授权
# 登录主库,创建repl用户(仅允许从库IP访问)
mysql -uroot -pMysql123! -e "
CREATE USER 'repl'@'192.168.200.101' IDENTIFIED BY 'Repl123@';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.200.101';
FLUSH PRIVILEGES;
"
3. 锁定主库并备份数据
# 锁定主库(禁止写入,保证备份一致性)
mysql -uroot -pMysql123! -e "FLUSH TABLES WITH READ LOCK;"
# 新开终端,备份主库所有数据
mysqldump -uroot -pMysql123! --all-databases --lock-all-tables > /root/master_backup.sql
# 查看主库binlog状态(记录File和Position,后续从库要用)
mysql -uroot -pMysql123! -e "show master status;"
# 示例输出:File=mysql-bin.000001,Position=154(以实际值为准)
# 解锁主库(备份完成后恢复写入)
mysql -uroot -pMysql123! -e "UNLOCK TABLES;"
# 把备份文件传到从库
scp /root/master_backup.sql root@192.168.200.101:/root/
四、从库(192.168.200.101)配置
1. 修改从库配置文件(开启中继日志 + 字符集)
cat > /etc/my.cnf << EOF
[mysqld]
server-id=2 # 从库唯一ID,不可与主库重复
relay-log=mysql-relay-bin # 开启中继日志(主从核心)
datadir=/data/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/data/mysql/localhost.localdomain.err
pid-file=/data/mysql/localhost.localdomain.pid
log-slave-updates=0 # 禁止从库写入binlog
replicate-ignore-db=mysql # 与主库一致,忽略系统库
replicate-ignore-db=information_schema
# 中文支持配置
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
EOF
# 重启从库使配置生效
systemctl restart mysqld
2. 解决 UUID 重复问题(关键避坑)
# 停止从库服务
systemctl stop mysqld
# 删除旧UUID文件(重启后自动生成新UUID)
rm -f /data/mysql/auto.cnf
# 重启从库
systemctl start mysqld
# 验证UUID(主库和从库UUID不同即为成功)
mysql -uroot -pMysql123! -e "SELECT @@server_uuid;"
3. 导入主库备份数据
# 导入主库备份(确保主从数据一致)
mysql -uroot -pMysql123! < /root/master_backup.sql
4. 配置主从连接并启动同步
# 登录从库,执行同步配置(替换File和Position为从主库记录的值)
mysql -uroot -pMysql123! -e "
CHANGE MASTER TO
MASTER_HOST='192.168.200.100',
MASTER_USER='repl',
MASTER_PASSWORD='Repl123@',
MASTER_LOG_FILE='mysql-bin.000001', # 主库show master status的File值
MASTER_LOG_POS=154; # 主库show master status的Position值
"
# 启动从库同步
mysql -uroot -pMysql123! -e "START SLAVE;"
5. 处理重复创建用户错误(必做)
# 跳过"重复创建repl用户"的SQL错误(备份已导入用户,binlog重复执行)
mysql -uroot -pMysql123! -e "
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter=1;
START SLAVE;
"
五、最终验证(从库执行,确认成功)
1. 检查主从同步状态(核心验证)
# 两个线程都为Yes即为成功
mysql -uroot -pMysql123! -e "show slave status\G;" | grep "Slave_IO_Running\|Slave_SQL_Running"
✅ 成功输出:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
2. 验证中文数据同步(功能验证)
# 主库执行:创建测试数据(含中文)
mysql -uroot -pMysql123! -e "
CREATE DATABASE IF NOT EXISTS test_sync;
USE test_sync;
CREATE TABLE IF NOT EXISTS student (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
INSERT INTO student (name) VALUES ('测试主从同步'), ('小白中文测试');
"
# 从库执行:查询是否同步成功(中文正常显示无乱码)
mysql -uroot -pMysql123! -e "SELECT * FROM test_sync.student;"
✅ 成功输出:
+----+------------------+
| id | name |
+----+------------------+
| 1 | 测试主从同步 |
| 2 | 小白中文测试 |
+----+------------------+
六、后续优化(提升稳定性,可选但推荐)
1. 从库设置只读(避免误操作)
mysql -uroot -pMysql123! -e "
SET GLOBAL read_only=1;
SET GLOBAL super_read_only=1;
"
2. 主库设置 binlog 过期清理(避免磁盘占满)
mysql -uroot -pMysql123! -e "
SET GLOBAL expire_logs_days=7;
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);
"
3. 创建同步监控脚本(快速检查状态)
cat > /root/check_repl.sh << EOF
#!/bin/bash
result=\$(mysql -uroot -pMysql123! -e "show slave status\G;" | grep "Slave_IO_Running\|Slave_SQL_Running")
echo "主从同步状态(\$(date)):"
echo "\$result"
echo "\$result" | grep -q "No" && echo "⚠️ 同步异常!执行:mysql -uroot -pMysql123! -e 'show slave status\G;' | grep 'Last_IO_Error\|Last_SQL_Error' 查看错误"
EOF
chmod +x /root/check_repl.sh
总结:
按以上流程执行后,主从复制已完全搭建成功,具备以下特性:
- 主从通信正常(IO+SQL 线程双 Yes);
- 数据实时同步(主库增删改自动同步到从库);
- 支持中文存储(无乱码、无插入报错);
- 避开所有坑(socket 路径、服务崩溃、UUID 重复、数据不一致等)。
日常使用直接在主库操作,从库自动同步,无需额外干预!