目录
- 一、什么是主从复制?
- 二、主从复制原理、存在问题和解决方法
- 三、主从复制之基于binlog日志方式
一、什么是主从复制?
总结:
实时灾备,用于故障切换;
读写分离,提供查询服务;
备份,避免影响业务。
主从复制必要的条件:
主库开启binlog日志(设置log-bin参数)
主从server-id不同
从库服务器能连同主库
二、主从复制原理、存在问题和解决方法
2.1.主从复制原理
master 负责写 -----A
slave relay-log -----B
I/o 负责通信读取binlog日志
SQL 负责写数据
2.2.主从复制存在的问题以及解决办法
- 问题
1.主库宕机之后,数据可能会丢失
2.从库只有一个sql Thread,主库写压力大,复制很可能延时 - 解决方法
解决数据丢失的问题:使用半同步复制的复制模型来解决
解决从库复制延时的问题:使用并行复制的方式来解决
2.3.主从复制的同步模型
总之,需要根据业务需求,平衡一致性、可用性和性能来选择合适的复制模式。
2.4.拓展—Mysql并行复制
-
并行复制的演进
MySQL最早的主备复制只有两个线程,IO 线程负责从主库接收 binlog 日志,并保存在本地的 relaylog 中,SQL线程负责解析和重放 relaylog 中的 event。当主库并行写入压力较大时,备库 IO 线程一般不会产生延迟,因为写 relaylog 是顺序写,但是 SQL线程重放的速度经常跟不上主库写入的速度,会造成主备延迟。如果延迟过大,relaylog 一直在备库堆积,还可能把磁盘占满。
在官方的5.6版本之前,MySQL只支持单线程复制,因此在主库并发高,TPS高时就会出现严重的主备延迟问题。从单线程复制到最新版本的多线程复制,中间的演化经历了好几个版本。
TPS是"Transactions Per Second"的缩写,表示每秒处理的事务数量。在数据库领域中,TPS是衡量数据库处理能力和性能的重要指标之一。它表示数据库系统每秒能够执行的事务操作的数量,包括读取和写入操作。较高的TPS值通常表示数据库具有更高的并发处理能力,可以处理更多的事务请求。
并行复制(Parallel Replication)指的是在一主多从的MySQL复制结构下,配置多个SQL线程去并发请求主库的二进制日志事件,实现从库并行重放日志来提高复制效率,缩短复制延迟。 -
并行复制的工作原理是:
主库将二进制日志打包成文件片段传输给从库
从库的多个I/O线程并行请求不同日志片段
从库根据文件名排序后写入relay log
多个SQL线程并行读取各自relay log位置并执行 -
MySQL并行复制是指在MySQL数据库中,可以同时复制多个事务到不同的slave实例上,以提高复制过程的效率。实现并行复制需要满足以下几个条件:
主服务器(master)上的日志事件必须按照顺序进行复制,不能进行并行复制。
同一事务中的多个日志事件必须按照顺序进行复制,不能进行并行复制。
不同事务之间的日志事件可以进行并行复制到不同的slave实例上。 -
在MySQL 5.6版本之后,MySQL引入了并行复制的功能,可以通过设置相关参数来启用并行复制。下面是一个配置mysql并行复制的示例代码:
首先,需要在主服务器和从服务器上都开启并行复制功能:
在主服务器的my.cnf文件中添加以下配置:
server-id = 1
log-bin = mysql-bin
binlog-format = row
slave-parallel-workers = 2
在从服务器的my.cnf文件中添加以下配置:
server-id = 2
relay-log = mysql-relay-bin
binlog-format = row
slave-parallel-workers = 2
然后,在从服务器上设置复制主服务器的相关信息:
mysql> CHANGE MASTER TO
MASTER_HOST='master-server',
MASTER_USER='replication',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=12345;
通过以上配置,可以使得从服务器上的复制进程可以并行复制来自主服务器的事务日志,提高数据复制的效率。
三、主从复制之基于binlog日志方式
3.1.bin-log日志简介
- Binlog是MySQL数据库中的二进制日志,用于记录数据库中所有修改操作,包括增删改等操作。binlog以二进制格式保存,可以通过解析binlog文件来查看数据库的操作历史记录。binlog日志可以用于数据恢复、数据备份、数据同步等场景。
- 在MySQL数据库中,binlog有三种模式:statement模式、mixed模式和row模式。statement模式记录的是SQL语句,row模式记录的是每一行数据的变化;mixed模式是自动组合 STATEMENT 和 ROW 模式,按照最优方式来记录日志。Binlog日志的开启和关闭可以通过设置MySQL的配置文件实现。
- Binlog的作用非常重要,它可以用来进行数据恢复和备份,也可以用来进行数据同步和复制。在进行数据恢复时,可以使用Binlog来恢复数据到某个时间点或某个操作之前的状态,从而保证数据的完整性。在进行数据备份时,可以将Binlog文件备份到另一台服务器上,以便在主服务器出现问题时,可以快速地将备份服务器恢复到与主服务器相同的状态。
- 除了数据恢复和备份外,Binlog还可以用来进行数据同步和复制。在进行数据同步时,可以将Binlog文件传输到其他服务器上,从而将数据同步到其他服务器中。在进行数据复制时,可以将Binlog文件传输到备份服务器上,从而将备份服务器上的数据与主服务器上的数据保持一致。
3.2.bin-log的使用
3.2.1.开启binlog
首先查看mysql是否开启binlog同步功能
mysql> show variables like 'log_bin';
默认是关闭的,此时需要开启,就要编辑mysql的配置文件,正常是在etc目录下
如果没有就先用 which mysqld查看位置
修改my.cnf配置
[root@localhost ~]# vim /etc/my.cnf
//[mysqld]开启binlog
log-bin = mysql-bin
也可以通过SET SQL_LOG_BIN=1
命令来启用 binlog,通过SET SQL_LOG_BIN=0
命令停用 binlog。
不过启用 binlog 之后须重启MySQL才能生效
3.2.2.常用的binlog命令
是否启用binlog日志show variables like 'log_bin';
查看详细的binlog日志配置信息show global variables like '%log%';
查看binlog的目录show global variables like "%log_bin%";
查看binlog文件日志列表show binary logs;
查看最新一个binlog日志文件名称和Position(操作事件pos结束点)show master status;
刷新log日志,自此刻开始产生一个新编号的binlog日志文件
每当mysqld服务重启时,会自动执行此命令,刷新binlog日志;在mysqldump备份数据时加 -F选项也会刷新binlog日志;flush logs;
查看第一个binlog文件内容show binlog events
查看具体一个binlog文件的内容show binlog events in 'master.000001';
重置(清空)所有binlog日志reset master;
删除slave的中继日志reset slave;
删除指定日期前的日志索引中binlog日志文件purge master logs before '2022-02-22 00:00:00';
删除指定日志文件purge master logs to 'master.000001';
3.2.3.使用binlog
1.使用mysqlbinlog自带查看命令法:
注: binlog是二进制文件,普通文件查看器cat more vi等都无法打开,必须使用自带的 mysqlbinlog 命令查看,binlog日志在同目录的data下
比如我刚刚建了一个表
mysql> CREATE TABLE IF NOT EXISTS `fungmu_table`( `id` INT UNSIGNED AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL, `age` VARCHAR(40) NOT NULL, `create_date` DATE, PRIMARY KEY ( `id` ))ENGINE=InnoDB DEFAULT CHARSET=utf8;
然后使用以下命令查看二进制日志
[root@localhost ~]# mysqlbinlog /usr/local/mysql/data/mysql-bin.000001
2.mysql命令行
直接查看binlog日志的话全文内容较多,不容易分辨查看pos点信息,这时候可以使用mysql命令行
mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
3.3.bin-log日志类型详解
3.3.1.Statement格式类型
3.3.2.Row格式类型
3.3.3.Mixed格式类型
3.3.4.如何选用bin-log的格式类型
3.3.5.bin-log的常用场景
1、mysql主从复制
2、mysql数据备份和恢复
3、数据同步,比如基于Canal投递MySQL Binlog到kafka、elasticsearch
3.3.6.bin-log和redo-log
3.4.基于binlog的主从复制实战操作
3.4.1.准备环境
1、准备环境两台机器,关闭防火墙和selinux;两台机器环境必须一致。时间也得一致
192.168.221.136 mysql-master
192.168.221.138 mysql-slave
2、两台机器安装mysql5.7(略)建议使用相同的安装方式
注意:
对主库已有的数据库不会进行自动同步。
主从同步之前,主库上已有数据库备份,需要在从库上手动导入同步。
3.4.2.配置master主服务
在主服务器上,必须启用二进制日志记录并配置唯一的服务器ID(server-id);修改配置文件后,需要重启mysql。
编辑主服务器的配置文件 my.cnf,添加如下内容
[root@mysql-master ~]# vim /etc/my.cnf //添加配置
[mysqld]
log-bin=/usr/local/mysql/logs/mysql-bin/mylog
server-id=1
创建日志目录并赋予权限
[root@mysql-master ~]# mkdir /usr/local/mysql/logs/mysql-bin/mylog -p
[root@mysql-master ~]# chown -R mysql:mysql /usr/local/mysql/
重启服务
[root@mysql-master ~]# systemctl restart mysqld
3.4.3.在主服务器上查看binlog以及POS点
mysql> show master status\G
*************************** 1. row ***************************
File: mylog.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
#记录下
File: mylog.000001
Position:154 Position:位置
3.4.4.创建主从同步的用户
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' identified by 'JiannLt@123';
mysql> flush privileges;
3.4.5.从服务配置slave
my.cnf配置文件,注意server-id不能相同
[root@mysql-slave ~]# vim /etc/my.cnf
[mysqld]
server-id=2
//修改完配置文件重启mysql服务
[root@mysql-slave ~]# systemctl restart mysqld.service
3.4.6.从库配置
mysql> CHANGE MASTER TO
MASTER_HOST='192.168.221.136',
MASTER_USER='repl',
MASTER_PASSWORD='JiannLt@123',
MASTER_LOG_FILE='mylog.000001',
MASTER_LOG_POS=154;
#参数解释:
MASTER_HOST='master2.example.com', #主服务器ip
MASTER_USER='replication', #主服务器用户
MASTER_PASSWORD='password', #用户密码
MASTER_PORT=3306, #端口
MASTER_LOG_FILE='master2-bin.001', #binlog日志文件名称
MASTER_LOG_POS=4, #日志位置
mysql> start slave;
mysql> show slave status\G
#查看状态,验证sql和IO是不是yes。
说明成功:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
3.4.7.数据同步测试
#主库新建数据库,从库检查同步情况
#主库新建库
mysql> create database testdb;
Query OK, 1 row affected (0.00 sec)
#从库查看
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
+--------------------+
5 rows in set (0.00 sec)
3.4.8.故障切换
mysql主从,master宕机,如何进行切换?
主机故障或者宕机:
1.在salve执行:
mysql> stop slave;
mysql> reset master;
2.查看是否只读模式:
mysql> show variables like 'read_only';
只读模式需要修改my.cnf文件,注释read-only=1并重启mysql服务。
或者不重启使用命令临时关闭只读,但下次重启后失效:set global read_only=off;
3.查看
mysql> show slave status \G;
4.在程序中将原来主库IP地址改为现在的从库IP地址,测试应用连接是否正常
3.4.9.故障排错
问题提示主从使用了相同的server UUID,一个个的检查:
检查主从server_id
检查主从状态:
#主库:
mysql> show master status
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#从库:
mysql> show slave status
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 306 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#File一样,排除。
最后检查发现他们的auto.cnf中的server-uuid是一样的。
[root@localhost ~]# vim /usr/local/mysql/data/auto.cnf
[auto]
server-uuid=4f37a731-9b79-11e8-8013-000c29f0700f
//修改uuid并重启服务
3.4.10.重设从库
#主库查看binlog,pos
mysql> show master status \G;
*************************** 1. row ***************************
File: mylog.000003
Position: 348
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)
#从库上操作
mysql> stop slave;
mysql> reset slave;
mysql> reset master;
#从库的binlog已经无效了,所以要执行这个命令清空binlog
CHANGE MASTER TO
MASTER_HOST='192.168.221.136',
MASTER_USER='slave',
MASTER_PASSWORD='JiannLt@123',
MASTER_LOG_FILE='mylog.000003',
MASTER_LOG_POS=348;
mysql> start slave;
mysql> show slave status\G
如果在没有故障的情况下进行从库的重设操作,那么进行change master后,会发现SQL线程不正常为NO
解决办法:(就是搞点错误出来测试)
将前面同步的库删掉,再执行上面的操作:stop slave/reset slave/reset master/change master……
建议:非故障的情况下不要随意重设从库操作