目录
一、环境
主服务器 | 从服务器 | |
操作系统 | Rocky 8.8 | Rocky 8.6 |
MySQL版本 | 8.0.32 | 8.0.32 |
IP | 10.0.0.151 | 10.0.0.152 |
注意:主服务器和从服务器的MySQL版本最好一致,如果不一致的话需要充分考虑兼容性问题。
二、主从复制原理
MySQL主从复制架构主要包括3个线程和2个日志。3个线程分别是dump线程、IO线程、SQL线程,2个日志分别是二进制日志(binlog)和中继日志(relay log)。
1、在master(主服务器)在进行写操作时会生成相应的二进制文件,二进制文件中记录了所有这些写的过程。
2、master会为每个slave(从服务器)节点上的IO线程提供一个dump线程,slave节点上的IO线程会向master请求二进制日志内容,然后master会将二进制日志通过dump线程提供给slave节点,然后由slave节点的IO线程写入本机的replay log(中继日志)中。
3、slave 节点上的 SQL 线程实时监测 replay log 内容是否有更新,如果更新,则将该文件中的内容解析 成SQL语句,还原到 slave 节点上的数据库中去,这样来保证主从节点之间的数据同步。
三、搭建一主一从
1、关闭主从服务器防火墙
查看防火墙状态:systemctl status firewalld.service
关闭防火墙:systemctl stop firewalld.service
2、关闭主从服务器SELINUX
进入SELINUX配置文件:
vim /etc/selinux/config
将SELINUX的值设置为disabled:
然后重启服务器(必须重启才能生效):
reboot
3、配置主服务器
a、配置master节点log_bin(二进制日志文件生成路径)以及server-id。
server-id是用来唯一标识MySQL服务器的,主从架构中的每个节点必须有不同的server-id,便于识别它们之间的身份和角色。
对于server-id,这里简单扩展一下:master和slave都可以生成二进制日志文件,在slave上是有可能发生同步外的写操作的,那在二进制日志中要如何辨别这个写操作是master同步过来的还是自己进行的呢?通过server-id,要不然都不知道数据从哪写入的了。
vim /etc/my.cnf
#加入以下内容到my.cnf中
[mysqld]
server-id=151
log_bin=/data/mysql/logbin/mysql-bin
b、因为二进制日志文件路径是我自定义不存在的路径,所以需要创建路径以及给文件添加权限。并重启MySQL服务。
#注意我这里没有创建mysql-bin,它是用来当二进制日志文件的前缀的,不需要创建
mkdir -pv /data/mysql/logbin
#给文件添加属主属组,-R表示递归
chown -R mysql.mysql /data/mysql/
#重启MySQL服务
systemctl restart mysqld.service
c、记录二进制日志的位置
这里的位置不是指文件路径,而是指二进制日志文件从哪里开始同步。在MySQL中输入show master status;进行查看。
d、创建具有复制权限的账号
#给10.0.0.0/24网段创建一个用户及密码,因为考虑到后面有其他同网段的主机做多从
create user slavenode@'10.0.0.%' identified by '123456';
#给这个用户授予复制权限,*.*表示所有库所有表
grant replication slave on *.* to slavenode@'10.0.0.%';
4、配置从服务器
a、修改配置文件并重启mysql服务
vim /etc/my.cnf
#添加以下内容到my.cnf中
[mysqld]
log_bin=/data/mysql/logbin/mysql-bin
server-id=152
read_only=on
relay_log=relay_log
relay_log_index=relay-log.index
read_only=on:将数据库设为只读;
log_bin这里路径也是我自己创建的,如果按这个路径需要去自己创建,并修改属主属组,并重启MySQL服务。
#注意我这里没有创建mysql-bin,它是用来当二进制日志文件的前缀的,不需要创建
mkdir -pv /data/mysql/logbin
#给文件添加属主属组,-R表示递归
chown -R mysql.mysql /data/mysql/
#重启MySQL服务
systemctl restart mysqld.service
relay_log=relay_log:指定中继日志文件路径,默认/var/lib/mysql/下
relay_log_index=relay-log.index:中继日志索引文件名
b、使用有复制权限的用户账号连接至主服务器,并启动复制线程
连接从服务器MySQL,输入show slave status,可以看到目前是空的:
输入下面语句:
CHANGE MASTER TO MASTER_HOST='10.0.0.151', #指定master节点
MASTER_USER='slavenode', #连接用户
MASTER_PASSWORD='123456', #连接密码
MASTER_LOG_FILE='mysql-bin.000001', #从哪个二进制文件开始复制
MASTER_LOG_POS=157, #指定同步开始的位置
MASTER_DELAY = 2; #可指定延迟复制实现防止误操作,单位秒,这里可以用作
延时同步,一般用于备份,默认是10s
再使用show slave status\G(\G的是以一种可读的形式显示):
可以看到刚刚配置的一些信息,并且可以发现目前IO线程和SQL线程处于关闭状态。实现主从同步需要依赖这俩个线程所以需要将它们开启。
c、开启IO线程以及SQL线程
连接MySQL输入start slave开启2个线程
#可以在后面跟线程名,开启具体线程;不跟线程名,则俩个线程都开启
start slave [IO_THREAD|SQL_THREAD];
再输入show slave status\G查看线程是否开启成功,这里都是yes说明开启成功
注意:这里如果Slave_IO_Running的值是connecting,可能是因为你主服务器的防火墙没有关,到主服务器中输入systemctl stop firewalld.service即可。再回从服务器输入show slave status\G查看是否值是否为Yes。
d、查看主服务器dump线程
dump线程不需要我们手动去配置,到这里其实主从配置已经完成了。进入主服务器MySQL,输入show processlist;查看dump线程:
show processlist;
5、验证主从同步
主服务器创建数据:
#创建数据库test
create database test;
#进入test
use test;
#创建表
CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
#插入数据
insert into student values(1,'tom',10,135,'M');
#查看插入的数据
select * from student;
从服务器查看数据:
#查看所有数据库,发现test已经同步过来
show databases;
#进入test库
use test;
#查看student表
select * from student;
主从比对:
四、Ubuntu
详细过程就不去赘述了,大部分配置过程与Rocky中一致,需要注意的有以下几点:
1、apparmor服务
apparmor它可以限制程序对一组列出的文件和权限的访问。
如果你在修改配置文件的时候指定了新的路径并且进行了授权,比如log_bin=/data/mysql/logbin/mysql-index,这个路径的权限不会被apparmor放行,所以你在重启mysql的时候会报错。
解决办法:
#修改apparmor配置文件
vim /etc/apparmor.d/usr.sbin.mysqld
#加入下面俩行内容,位置随意(注意格式,逗号不要省略)
/data/mysql/logbin/ r,
/data/mysql/logbin/** rwk,
#重启apparmor
systemctl restart apparmor.service
2、caching_sha2_password
从 MySQL 8.0.4 开始,MySQL 默认身份验证插件从mysql_native_password改为了caching_sha2_password 。mysql_native_password的特点是不需要加密验证,所以它的验证速度很快,但是不安全。
所以基于以上信息,如果你使用的mysql版本大于8.0.4,那么在Ubuntu中配置MySQL主从大概在开启slave节点后会报错:
Last_IO_Error: Error connecting to source 'slavenode@10.0.0.161:3306'. This was attempt 1/86400, with a delay of 60 seconds between attempts. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
报错也说明了原因,'caching_sha2_password'认证插件需要安全的连接,言外之意就是现在连接不安全呗。
那把身份认证插件改为mysql_native_password?这种做法大概也是可以的。
不过不建议了,因为是不安全的,所以这样做;
进入从服务器上mysql的时候多加一个参数:
mysql -uroot -p123456 --get-server-public-key
然后在change master to的时候多加一行(先reset slave all):
CHANGE MASTER TO
MASTER_HOST='10.0.0.161',
MASTER_USER='slavebak',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=157,
get_master_public_key=1;
然后start slave即可。
3、max_connect_errors
max_connect_errors是用来指定允许连接不成功的最大尝试次数,默认是100,可以通过以下命令查看:
show global variables like '%max_connect_errors%';
因为我在解决2中出现的问题的时候尝试了太多次,大概是超过了100次,所以在start slave后出现了以下报错:
Last_IO_Error: Error connecting to source 'slavebak@10.0.0.161:3306'. This was attempt 1/86400, with a delay of 60 seconds between attempts. Message: Host '10.0.0.162' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
翻译以下报错就是:主机10.0.0.162被锁住了,因为太多连接错误,解锁用mysqladmin flush-hosts命令。
所以我进入俩边数据库:
flush hosts;
再重启slave后,IO线程正常了,无报错。
以上内容仅供参考,有问题请私信或评论,thanks~