原理
三种线程
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原理
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.