原理

image-1665421359180

三种线程

binlog dump thread
根据从节点IO thread的请求,分批读取binlog文件指定位置之后的信息并返回从节点
io thread
当从节点执行START SLAVE命令开启主从复制后,从节点会创建IO thread用来连接主节点,请求指定binlog,指定位置之后的日志内容,并将获得的内容存到relay log
sql thread
检测relay log新增的内容,并将relay log内容解析成具体的SQL,在从节点按照位置顺序执行,从而保证主从节点数据一致

变量名称 作用
log_bin 是否开启binlog
log_bin_basename binlog的基路径与名称
log_bin_index binlog索引文件的路径与名称
log_bin_trust_funciton_creators 是否可以信任存储函数创建者,不会创建写入二进制日志引起不安全事件的存储函数。如果设置为 0(默认值),用户不得创建或修改存储函数,除非它们具有除 CREATE ROUTINE 或 ALTER ROUTINE 特权之外的 SUPER 权限。 设置为 0 还强制使用 DETERMINISTIC 特性或 READS SQL DATA 或 NO SQL 特性声明函数的限制。 如果变量设置为 1,MySQL 不会对创建存储函数实施这些限制。 此变量也适用于触发器的创建
log_bin_use_v1_row_events 使用早期版本(MySQL 5.5或更早)的记录方式,而非新版(MySQL5.6或更高)方式, 此配置MySQL8.18已废弃
sql_log_bin 用于精准控制当前会话是否要记录binlog
binlog_format 用来指定binlog的格式,1.Statement:基于SQL语句,每条修改数据的SQL都会存储到binlog文件里2.Rom:基于行,每行数据的变化都记录到binlog文件里,但是不记录原始SQL3.Mixed 混合模式
binlog_xxx 使用show variables lkie ‘%binlog%’

基础
查看所有binlog文件信息
show master logs;
查看指定binlog文件中的事件
show binlog event in ‘binlog.000001’
查看指定binlog文件中从指定位置(position)开始的所有事件
show binlog events in ‘binlog.000001’ from 32556’
分页查询
show binlog events in ‘binlog.000001’ from 32556 limit 10;

使用binlog_format后无法使用 binlog查询
需要使用
mysqlbinlog -vv /var/lib/mysql/binlog.000001指令查询

Statement

优点:记录的是执行的SQL,比较省空间,降低了主从复制时的IO开销
缺点:由于记录的是SQL,所以MySQL多个节点之间复制的时候,特定场景下会导致数据不一致的情况

Row

优点:记录的是每条数据的变化,内容比较容易理解,不会有多个节点数据不一致的问题
缺点:由于记录得是每行数据的变化,所以占用的空间较大,特别是对于字段较多的表的操作,大批量操作来说

MySQL主从复制的部署架构

单向复制,双向复制,链式级联,环状复制

MySQL 主从复制的方式

异步复制

默认的复制方式
主节点写入binlog文件后就返回客户端,不考虑binlog是否已完整同步到从节点,是否已完整存放到从节点的relay log中去
优点:性能好,无阻塞
缺点:如果主节点发生宕机,主节点上已提交的事务尚未同步到从节点,如果此时强行将节点晋升为主节点,会导致新主节点数据不完整

主从搭建的相关配置

参数 作用
server_id MySQL唯一标识,主从节点上不能相同
binlog_format binlog日志格式
read_only 限制普通用户只读不可写,但不会限定具有CONNECTION_ADMIN(即之前的SUPER)权限用户的操作
super_read_only 限制普通用户、超级管理员用户的写操作
relay_log_recovery 是否要自动恢复relay log,建议开启
master_info_repository 如果配置成TABLE,则将源相关的元数据(状态、连接信息等)记录到mysql.slave_master_info表中;如果配置成FILE,则记录成文件。目前8.0.23已废弃,默认是TABLE,如果想用FILE,改用 master-info-file
relay_log_info_repository 如果设为TABLE,则使用mysql.slave_relay_log_info表记录元数据;也可设置成FILE,用文件记录。该配置8.0.23已废弃,暂未找到用FILE时的替代参数
gtid_mode 设置GTID模式,取值如下:1. OFF:新事务是非GTID,从节点只接受不带GTID的事务,传过来的的GTID事务会报错2. OFF_PERMISSIVE:新事务是非GTID,从节点既接受不带GTID的事务也接受带GTID的事务 3. ON_PERMISSIVE:新事务是GTID,从节点既接受不带GTID的事务也接受带GTID的事务 4. ON:新事务是GTID,Slave只接受带GTID的事务需要注意的是,该参数的值是有顺序的:OFF ←→ OFF_PERMISSIVE←→ ON_PERMISSIVE ←→ ON,不能跳跃执行
enforce_gtid_consistency 是否限定事务安全的SQL才允许被记录。例如:create table…select语句以及create temporary table语句不被允许执行
log_salve_updates 是否要将从master上获取数据变更的信息记录到slave的二进制日志文件中。对于级联复制A→B→C,也就是说,A为从服务器B的主服务器,B为从服务器C的主服务器。为了能工作,B必须既为主服务器又为从服务器。为了能工作,B必须既为主服务器又为从服务器。除了A和B启用二进制日志外,B服务器还必须启用log-slave-updates选项。另外,MySQL 5.6的GTID复制模式也必须开启log_slave_updates参数,否则启动就会报错,因为需要在bin-log找到同步复制的信息。从MySQL 5.7开始,官方做了调整,用一张gtid_executed系统表记录同步复制的信息,可以不开启log_slave_updates

异步复制搭建

必要条件

  • 确保主从节点操作系统版本与位数一致
  • 确保主从节点的MySQL版本一致
  • 确保主库已经开启binlog,对于MySQL 8.0默认就是开启的
  • 建议从库也开启binlog,并且开启log_slave_updates,方便后期扩展架构
  • 确保主从节点的server_id不重复
    根据你项目的需要,选择合适的binlog格式,MySQL 8.0默认就是row。

主节点

在 /etc/my.cnf 添加

[mysqld]
server-id=1
log-bin=mysql-binlog
binlog_format=row

从节点

在 /etc/my.cnf 添加

[mysqld]
server-id=2
log-bin=mysql-binlog
binlog_format=row
log_slave_updates=on
relay_log_recovery=1

创建连接用户

在主节点创建一个用户,用于从节点连接主节点
这里推荐使用图形化工具添加

重启服务

systemctl restart mysqld.service

备份主节点数据

mysqldump -uroot -proot123 --single-transaction --master-data=2 --databases test_replication >/opt/test_replication.dmp

–single-transaction 将整个备份过程放入一个事务
–master-data=2 在dump文件中获得主从复制所需要的信息

使用more命令查看dump文件,获得master_log_file

上传dump文件至从节点,并恢复备份

mysql -uroot -proot123 < /opt/test_replication.dmp

配置主从

change master to master_host=‘192.168.248.128’,master_port=3306,master_user=‘rep1’,master_password=‘root123’,master_log_file=‘binlog.000001’,master_log_pos=120,get_master_public_key=1;

https://dev.mysql.com/doc/refman/8.0/en/change-master-to.html
开启从机
start slave;
查看从机状态
show slave status
查看主机状态
show master status;

判断是否配置成功
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

暂停主从
stop slave

半同步复制

全同步复制

主节点在写入binlog后等待从库所有事务提交后,在返回客户端
优点:确保数据实时同步到了所有从库
缺点:数据库更新效率会很差,增删改等操作会有较大延迟

半同步复制

主库提交事务后,不立即返回,而是等待至少一个从库接收到binlog,并写入relay log才返回,从而保证从库出问题时,至少有一个从库的数据是完整的

  • 当等待超时时,会降低到异步复制,保证从库的正常更新
    5.6之前半同步复制after-commit

存在问题
主库在等待从库确认ACK时,尽管没有返回给客户端,但是事务已被提交了,如果在binlog还未发送到从库瞬间,从库发生宕机,那么主从切换后新的从库无法读到尚未同步过来的数据

5.7之后的半同步复制
通过rpl_semi_sync_master_wait_point设置

  • AFETER_SYNC

5.7的半同步复制性能改进
之前:dump thread既要传binlog给从节点,又要等待从节点返回信息,两个任务串行执行,性能不佳
5.7开始独立出一个ACK Collector Thread,专门用来接收从节点的反馈信息,这样可以同时发送binlog到从节点,并同时接收从节点的反馈,性能提升

并行复制是为了解决主从复制间延迟的

GTID复制

GTID

全局事务标识,是对一个已提交事务的编号,并且全局唯一,一个事务对应一个GTID,由UUID+TID组成,UUID是MySQL实例的唯一标识,TID则是事务在该实例上提交的顺序

GTID复制

无需指定binlog文件名以及binlog中position

GTID原理

image-1665459932022

GTID复制搭建

GTID复制需要基于异步复制或者半同步复制,所以首先要搭建好异步复制或者半同步复制的环境

多源复制

适用场景
数据分析团队可能要分析多个微服务的数据,可使用多源复制,将多个微服务的数据复制到一个数据库中去,以便统一分析
数据备份,一个大型项目往往有多个微服务,多个数据库实例,可以把多个数据库复制到一个数据库实例实现数据备份

多源复制搭建

在从节点配置文件中加入
[mysqld]
master_info_repository=TABLE
relay_log_info_repository=TABLE

MySQL 8.0 这两个参数已经废弃

借助分别将从库指向两个主库
CHANGE MASTER TO MASTER_HOST=‘192.168.10.128’,MASTER_USER=‘repl’, MASTER_PASSWORD=‘123456’,MASTER_LOG_FILE=‘Master_1-bin.000001’,MASTER_LOG_POS=1539 FOR CHANNEL ‘M1’;

CHANGE MASTER TO MASTER_HOST=‘192.168.10.129’,MASTER_USER=‘repl’, MASTER_PASSWORD=‘123456’,MASTER_LOG_FILE=‘Master_2-bin.000003’,MASTER_LOG_POS=630 FOR CHANNEL ‘M2’;

开启主从复制
start slave for CHANNEL ‘M1’;

start slave for CHANNEL ‘M2’;

查看同步状态
SHOW SLAVE STATUS FOR CHANNEL ‘M1’\G

SHOW SLAVE STATUS FOR CHANNEL ‘M2’\G

Q.E.D.