引言:
最近因为时间缘故,学校,比赛,面试很久没有更新了,现在开始将会持续更新!!!欧克。我们往下看:
概述:
主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进行复制,从库同时也可以作为其他从服务器的主库,实现链状复制。
好处是 :
-
主库出现问题,从库可以快速提供服务
-
降低主库的压力,实习读写分离,
-
可以在从库中去备份文件,避免备份期间影响主库服务 (数据之间存在延迟)
缺点:
1. 数据一致性问题 。从库数据同步存在延迟,无法保证实时一致性
2. 单点故障问题,虽然从库可以接管,但主库宕机期间无法写入的
3. 资源消耗啊,配置和维护复杂性等...
原理:
其实之间的数据一致性主要是靠的日志文件中的二进制日志文件 -> Binlog 日志文件,主库对数据的增删改(DDL) 和 对表库结构的更改(DML) 都会记录到这个二进制日志文件中去,然后从库有两组线程,一组IOthread 线程 一组SQLthread 线程,当配置好用户权限后,IOthread线程会发送一个请求来连接指定的主库,对取主库中的Binlog 日志文件的内容,然后写到自己的一个Relay log (中继日志)文件中去,然后另一组线程SQLthread 会去读取这个中继日志文件的数据变化,然后去执行写入到自己的数据库中去就保证了主从复制 !!!
插曲疑问:为什么不直接读取到binlog 日志的内容修改直接写到从库中去呢?还多一个中继日志
这里的中继日志 有点缓冲区的味道,而且有着性能优化作用,写入中继日志也是顺序,直接库表容易数据IO
小插曲: 主从复制如何推事件的 :
MySQL实际机制 | 长连接+文件事件监听 | 低(无轮询) | 毫秒级 |
主从复制依赖于从库 I/O 线程主动连接主库并请求 binlog 数据。主库通过 Binlog Dump 线程响应请求,并在有新数据时立即发送(利用阻塞等待机制实现高效“准推送”),而不是主库主动推送或持续通知从库。
Binlog Dump : 主库收到从库的请求后,会为这个特定的从库连接创建一个专门的
Binlog Dump
线程。每个成功连接的从库在主库上都有自己的 Binlog Dump 线程。
Binlog Dump 线程读取主库上的 binlog 文件。
它检查从库请求的 binlog 文件名和位置:
如果请求的位置在当前的 binlog 文件内,则从这个位置开始读取后续事件。
如果请求的位置在更早的 binlog 文件(主库可能已经进行了 binlog 轮转,旧的 binlog 文件可能已被删除或归档),Binlog Dump 线程会尝试找到最早可用的 binlog 文件开头,或者报错(如果文件不可用)。
如图:
从上图来看,复制分成三步:
-
Master主库在事务提交时,会把数据变更记录在二进制日志文件Binlog中。
-
从库读取主库的二进制日志文件 Binlog,写入到从库的中继日志 Relay Log。
-
slave重做中继日志中的事件,将改变反映它自己的数据。
搭建:
这里我就直接使用了虚拟机通过Docker 来创建2个容器来模拟主从库,其效果也是一致的 !!!
1. 拉取MySQL镜像
docker pull mysql:8.0
2. 创建网络(这里方便让容器可以互相通信,后续主库连接使用)
docker network create mysql-replication-net
3. 启动主服务器(Master)
docker run -d --name mysql-master \--network mysql-replication-net \-e MYSQL_ROOT_PASSWORD=rootpassword \-p 3306:3306 \-v mysql-master-data:/var/lib/mysql \mysql:8.0 \--server-id=1 \--log-bin=mysql-bin \--binlog-format=ROW \--character-set-server=utf8mb4 \--collation-server=utf8mb4_unicode_ci
参数:
--name mysql-master 为容器指定名称
mysql-master
,便于后续管理--network mysql-replication-net
--server-id=1 指定集群服务下 的 id 为1 从库不能重复
--read-only=0 这里没有指定,默认就是0表示读写 1 表示只读
--log-bin=mysql-bin 这里显示启用二进制日志,指定日志文件的前缀为mysql-bin ,MySQL 8.0 默认就开启了
--binlog-format=ROW 这里指定二进制日志文件记录方式为 ROW 模式 (默认也就是ROW)
如图创建并且启动一个主库:
4. 配置主服务器
4.1: 接入主服务器容器:
docker exec -it mysql-master mysql -uroot -prootpassword
4.2 : 创建远程连接账号,并授予主从复制权限:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpassword';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
注: 这里我测试环境,同时指定插件为mysql_native_password,避免 MySQL 8.0 默认的 caching_sha2_password
导致的从库连接问题(无需额外配置 SSL)。
4.3 :查看二进制日志的坐标
SHOW MASTER STATUS;
这里记住二进制日志文件,还有行数,后续便于从库定位,决定从哪里开始复制!!!
5. 启动从服务器(Slave)
docker run -d --name mysql-slave \
--network mysql-replication-net \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-p 3307:3306 \
-v mysql-slave-data:/var/lib/mysql \
mysql:8.0 \
--server-id=2 \
--log-bin=mysql-bin \
--binlog-format=ROW \
--relay-log=mysql-relay-bin \
--log-slave-updates=1 \
--read-only=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
如图:
参数:
这里的 --read-only =1 表示当前的库只是只读,同时指定--server-id = 2 表示当前的服务id 不要重复即可!
6. 配置从服务器
6.1进入从服务器容器:
docker exec -it mysql-slave mysql -uroot -prootpassword
6.2 执行sql语句 (来连接主库)
这里的参数要和上面的一致
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='replpassword',
MASTER_LOG_FILE='mysql-bin.000006',
MASTER_LOG_POS= 544;
-- 检查从服务器状态
7. 开始测试:
首先我们从库主库开始都只有系统表如下:
我们开始操作主库:
创建一个hz_mn库, 同时在里面创建一个学生表,student 表,然后插入一些数据即可
如下:
CREATE DATABASE IF NOT EXISTS hz_mn;USE hz_mn;CREATE TABLE IF NOT EXISTS student (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(255),age INT
);INSERT INTO student(name, age) VALUES('hz', 19);SELECT * FROM student;
如图:
docker exec -it mysql-master mysql -uroot -prootpassword
然后去查看从库:
docker exec -it mysql-slave mysql -uroot -prootpassword
可以看到 从库 已经同步成功了,也出现了相应的库hz_mn 和表 student,查询student表的情况:
select * from student;
欧克,没有问题,我们主从复制也就搭建完成了 !!!
总结:
主从复制是MySQL高可用架构的基础,理解其原理并掌握搭建方法对于数据库管理员至关重要。通过合理配置,可以实现读写分离、负载均衡、数据备份等多种应用场景。
欧克,我们下次再见