mysql主从复制原理及一主一从搭建过程—2023.04
Posted 我是小bā吖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql主从复制原理及一主一从搭建过程—2023.04相关的知识,希望对你有一定的参考价值。
文章目录
一、mysql主从复制介绍
1、主从复制概念
MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。
MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。
2、为什么要做主从复制
-
在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
-
做数据的热备
-
架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
3、主从复制原理
- 原理
- master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时,则将其改变写入二进制日志中;
- slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/OThread请求master二进制事件;
- 同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志(relay-log)中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。
也就是说:
- 从库会生成两个线程,一个I/O线程,一个SQL线程;
- I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;
- 主库会生成一个log dump线程,用来给从库I/O线程传binlog;
- SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;
- 具体步骤:
- 从库通过手工执行change master to 语句连接主库,提供了连接的用户一切条件(user 、password、port、ip),并且让从库知道,二进制日志的起点位置(file名 position 号); start slave
- 从库的IO线程和主库的dump线程建立连接。
- 从库根据change master to 语句提供的file名和position号,IO线程向主库发起binlog的请求。
- 主库dump线程根据从库的请求,将本地binlog以events的方式发给从库IO线程。
- 从库IO线程接收binlog events,并存放到本地relay-log中,传送过来的信息,会记录到master.info中
- 从库SQL线程应用relay-log,并且把应用过的记录到relay-log.info中,默认情况下,已经应用过的relay 会自动被清理purge
- 主从同步事件binlog模式有3种形式:
statement
、row
、mixed
。
statement
: 会将对数据库操作的 sql 语句写入到 binlog 中。row
: 会将每一条数据的变化写入到 binlog 中。mixed
: statement 与 row 的混合。MySQL 决定什么时候写 statement 格式的,什么时候写 row 格式的 binlog。
- 注意:
①master将操作语句记录到binlog日志中,然后授予slave远程连接的权限(master一定要开启binlog二进制日志功能;通常为了数据安全考虑,slave也开启binlog功能)。
②slave开启两个线程:IO线程和SQL线程。其中:IO线程负责读取master的binlog内容到中继日志relay log里;SQL线程负责从relay log日志里读出binlog内容,并更新到slave的数据库里,这样就能保证slave数据和master数据保持一致了。
③Mysql复制至少需要两个Mysql的服务,当然Mysql服务可以分布在不同的服务器上,也可以在一台服务器上启动多个服务。
④Mysql复制最好确保master和slave服务器上的Mysql版本相同(如果不能满足版本一致,那么要保证master主节点的版本低于slave从节点的版本)
⑤master和slave两节点间时间需同步
4、主从复制形式
- 一主多从,提高系统的读性能
一主一从和一主多从是最常见的主从架构,实施起来简单并且有效,不仅可以实现HA,而且还能读写分离,进而提升集群的并发能力。- 多主一从 (从5.7开始支持)
多主一从可以将多个mysql数据库备份到一台存储性能比较好的服务器上。- 双主复制
双主复制,也就是互做主从复制,每个master(主)既是master,又是另外一台服务器的slave(从)。这样任何一方所做的变更,都会通过复制应用到另外一方的数据库中。- 级联复制
级联复制模式下,部分slave的数据同步不连接主节点,而是连接从节点。因为如果主节点有太多的从节点,就会损耗一部分性能用于replication(复制),那么我们可以让3~5个从节点连接主节点,其它从节点作为二级或者三级与从节点连接,这样不仅可以缓解主节点的压力,并且对数据一致性没有负面影响。级联复制下从节点也要开启binary log(bin-log)功能。
5、主从复制主要用途
- 读写分离
在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。 - 数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换(主从切换)
提高数据安全-因为数据已复制到从服务器,从服务器可以终止复制进程,所以,可以在从服务器上备份而不破坏主服务器相应数据; - 高可用(HA)
1)因为数据库服务器中的数据都是相同的,当Master挂掉后,可以指定一台Slave充当Master继续保证服务的运行,因为数据是一致性的(如果当插入时Master就挂掉,可能不一致,因为同步也需要时间)当然这种配置不是简单的把一台Slave充当Master,毕竟还要考虑后续的Slave的数据同步到Master
2)在主服务器上执行写入和更新,在从服务器上向外提供读功能,达到读写分离的效果,也可以动态地调整从服务器的数量,从而调整整个数据库的性能。
3)在主服务器上生成实时数据,而在从服务器上分析这些数据,从而提高主服务器的性能。 - 架构扩展
随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据存储节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的频率,提高单个机器的I/O性能。
二、MySQL一主一从搭建
1、准备工作
服务器 | IP | 要求 |
---|---|---|
master | 192.168.2.31 | Docker、MySQL5.7 |
slave | 192.168.2.32 | Docker、MySQL5.7 |
首先在两台服务器上提前部署好docker以及MySQL5.7版本。
MySQL安装流程参考这篇文章:https://blog.csdn.net/weixin_64124795/article/details/129110551
2、MySQL主从复制部署流程
1. 关闭防火墙,两台主机都操作
systemctl stop firewalld 关闭防火墙
systemctl disable firewalld 关闭开机自启
2. 修改配置文件,两台主机都操作
mysql配置文件路径:/etc/my.cnf
增加如下内容:
# MySQL 服务的唯一编号,每个 MySQL 服务的 id 需唯一
server-id = 1
# 服务端口号,默认为 3306
port = 3306
# 是否对sql语句大小写敏感,默认值为0,1表示不敏感
lower_case_table_names=1 #1代表关闭大小写区别 0代表开启大小写
default_storage_engine=InnoDB #存储引擎 lnnoDB
# 配置默认编码为utf8
character_set_server=utf8
init_connect=\'SET NAMES utf8\'
最终配置文件内容:
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
# MySQL 服务的唯一编号,每个 MySQL 服务的 id 需唯一
server-id = 1
# 服务端口号,默认为 3306
port = 3306
# 是否对sql语句大小写敏感,默认值为0,1表示不敏感
lower_case_table_names=1 #1代表关闭大小写区别 0代表开启大小写
default_storage_engine=InnoDB #存储引擎 lnnoDB
# 配置默认编码为utf8
character_set_server=utf8
init_connect=\'SET NAMES utf8\'
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
重启mysql使配置生效
systemctl restart mysqld
默认配置文件路径:
配置文件:/etc/my.cnf
日志文件:/var/log/mysqld.log
服务启动脚本:/usr/lib/systemd/system/mysqld.service
socket文件:/var/lib/mysql/mysql.sock
3. 修改主节点配置文件,主节点操作
vim /etc/my.cnf
添加以下参数:
log-bin=mysql-bin #启动二进制日志系统
binlog-do-db=test #二进制需要同步的数据库名,如果需要同步多个库,例如要再同步westos库,再添加一行“binlog-do-db=westos”,以此类推
binlog-ignore-db=mysql #禁止同步 mysql 数据库
# 重启mysql
systemctl restart mysqld
- 配置主服务器用户并清空日志
进入MySQL
mysql -uroot -p
mysql> show privileges;
# 注意这里的密码不能设置的太简单,否则会报错 ERROR 1819 (HY000): Unknown error 1819
mysql> grant replication client,replication slave on *.* to \'tongwz\'@\'192.168.2.%\' identified by \'Tongwz123.\';
mysql> reset master;
mysql> show binary logs;
4. 修改从节点配置文件,从节点操作
/etc/my.cnf
中的server-id 改为2, 注意:server-id不可跟主服务器的一样
# 重启mysql
systemctl restart mysqld
进入MySQL:
mysql -uroot -p
执行如下命令:
mysql> change master to master_host=\'192.168.2.31\', master_user=\'tongwz\', master_password=\'Tongwz123.\', master_port=3306, master_log_file=\'mysql-bin.000001\', master_log_pos=154;
说明:
# change master to master_host=‘主服务器ip’,
# master_user=‘刚在主服务器创建的用户名’,
# master_password=‘刚在主服务器创建的用户密码’,
# master_port=3306,
# master_log_file=‘刚查看主服务器下的File值’,
# master_log_pos=刚查看主服务器下的Position值,必须要一致
先查看slave状态:红框中显示是No,由于slave还没有开启,表示还没有加入主节点
mysql> show slave status \\G;
正式开启slave:
mysql> start slave;
再次查看状态:此时已经显示为Yes了
mysql> show slave status \\G;
注意:两个必须都显示为Yes才表示成功,否则就要重新执行change master to master_host=\'192.168.2.31\', master_user=\'tongwz\', master_password=\'Tongwz123.\', master_port=3306, master_log_file=\'mysql-bin.000001\', master_log_pos=154;
这段命令,在执行这段命令前还需要通过show binary logs;
命令查看master节点aster_log_pos
值。
此时,slave已经配置好,进一步查看:
# 查看relay-log.info文件位置,进入查看
find / -name relay-log.info
cat /var/lib/mysql/relay-log.inf
# 查看master.info文件位置,进入查看
find / -name master.info
cat /var/lib/mysql/master.info
5. 测试
在master节点中数据库test
里创建表test
,插入数据;在slave节点查看数据是否同步。
因为前面配置文件中,写明了只同步test数据库。
master节点中创建:
mysql> use test;
mysql> create table test(id int(11));
mysql> insert into test values(1);
mysql> select * from test;
slave节点中查看:
mysql> use test;
mysql> show tables;
mysql> select * from test;
可以看到在master节点上加入的数据,这就
6. 特别说明
- 以上这种方式搭建的一主一从,主要实现读写分离,master节点上写入数据会自动同步到slave节点。如果反过来,在slave节点写入数据,是无法同步到master节点上的,反而还会中断主节点与从节点的连接。所以为了避免这个问题,一般只给slave节点只读的权限。
增加同步的数据库到slave
- 上面的操作我们只同步了
test
数据库,如果我们想要再同步一个数据库到slave节点,该怎么操作呢?
首先,我们要修改master节点的配置文件vim /etc/my.cnf
,里面增加数据库test1
master节点操作:
vim /etc/my.cnf
binlog-do-db=test #二进制需要同步的数据库名,如果需要同步多个库,例如要再同步westos库,再添加一行“binlog-do-db=westos”,以此类推
binlog-do-db=test1 # 增加这一行
然后重启
systemctl restart mysqld
然后,进入slave节点的mysql中,等待从节点同步主节点数据,待查看状态show slave status \\G;
后,两行都显示为Yes,表示已经连接成功;
其次,再master节点上的mysql中创建test1数据库,并往数据库内创建表,写入内容;
最后到slave节点查看是否同步即可。
注意:
必须先修改配置文件中的数据库名称,然后待slave与master连接后,再在master上创建test1数据库,顺序不能改变。
如果反过来,先在master节点上创建了test1数据库,然后修改配置文件、slave连接master,那么所创建的数据库就不会同步到slave。
所以,顺序很重要。
slave只同步连接master节点后,在master节点上执行的命令。
mysql搭建主从复制(一主一从,双主双从)
主从复制原理
Mysql 中有一个binlog 二进制日志,这个日志会记录下所有修改了的SQL 语句,从服务器把主服务器上的binlog二进制日志在指定的位置开始复制主服务器所进行修改的语句到从服务器上执行一遍。
流程图
2|0搭建一主一从
2|1 前期环境准备
Linux:centos7
mysql版本:mysql5.7(安装教程:https://blog.csdn.net/weixin_45797918/article/details/104929127)
主服务器:10.10.10.130
从服务器:10.10.10.133
2|2修改配置文件
主机配置
vim /etc/my.cnf
添加配置
#主服务器唯一ID
server-id=1
#启用二进制日志
log-bin=mysql-bin
#设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
#设置logbin格式
binlog_format=STATEMENT
从机配置
vim /etc/my.cnf
添加配置
#从服务器唯一ID
server-id=2
#启用中继日志
relay-log=mysql-relay
2|3配置主机
在主机MySQL里执行授权命令
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123456';
查询master的状态
show master status;
#记录下File和Position的值
#执行完此步骤后不要再操作主服务器MySQL,防止主服务器状态值变化
2|4配置从机
在主机MySQL里执行
CHANGE MASTER TO MASTER_HOST='10.10.10.130', MASTER_USER='slave', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
CHANGE MASTER TO MASTER_HOST=‘主机的IP地址’,
MASTER_USER=‘slave’,
MASTER_PASSWORD=‘123456’,
MASTER_LOG_FILE=‘mysql-bin.具体数字’,MASTER_LOG_POS=具体值;
启动从服务器复制功能
start slave;
查看从服务器状态
show slave status\\G;
2|5测试一主一从
主机创建testdb数据库和表user
从机直接刷新
3|0搭建双主双从
3|1前期环境准备
Master1:10.10.10.130
Slave1:10.10.10.133
Master2:10.10.10.134
Slave2:10.10.10.135
3|2停止一主一从(没有启动的跳过)
从机上执行
stop slave;
重设
reset slave;
删除主机从机testdb数据库
3|3修改配置文件
编辑Master1
修改配置文件,添加
vim /etc/my.cnf
#主服务器唯一ID
server-id=1
#启用二进制日志
log-bin=mysql-bin
#设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
#设置logbin格式
binlog_format=STATEMENT
#在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 … 65535
auto-increment-increment=2
#表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 … 65535
auto-increment-offset=1
编辑Master2
修改配置文件,添加
vim /etc/my.cnf
#主服务器唯一ID
server-id=3
#启用二进制日志
log-bin=mysql-bin
#设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
#设置logbin格式
binlog_format=STATEMENT
#在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 … 65535
auto-increment-increment=2
#表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 … 65535
auto-increment-offset=2
编辑Slave1
修改配置文件,添加
vim /etc/my.cnf
#从服务器唯一ID
server-id=2
#启用中继日志
relay-log=mysql-relay
编辑Slave2
修改配置文件,添加
vim /etc/my.cnf
#从服务器唯一ID server-id=4 #启用中继日志 relay-log=mysql-relay
3|4Master1、Master2授权slave并查看状态
Master1主机
MySQL里执行授权命令
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123456';
Master1
show master status;
Master2主机
MySQL里执行授权命令
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123456';
Master1
show master status;
3|5启动双主双从
Slave1
执行
CHANGE MASTER TO MASTER_HOST='10.10.10.130', MASTER_USER='slave', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=766;
启动两台从服务器复制功能
start slave;
查看从服务器状态
show slave status\\G;
Slave2
执行
CHANGE MASTER TO MASTER_HOST='10.10.10.134', MASTER_USER='slave', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
启动两台从服务器复制功能
start slave;
查看从服务器状态
show slave status\\G;
两个主机互相复制
Master2
执行
CHANGE MASTER TO MASTER_HOST='10.10.10.130', MASTER_USER='slave', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=766;
启动两台从服务器复制功能
start slave;
查看从服务器状态
show slave status\\G;
Master1
执行
CHANGE MASTER TO MASTER_HOST='10.10.10.134', MASTER_USER='slave', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
启动两台从服务器复制功能
start slave;
查看从服务器状态
show slave status\\G;
#复制主机的命令
CHANGE MASTER TO MASTER_HOST=‘主机的IP地址’,
MASTER_USER=‘slave’,
MASTER_PASSWORD=‘123456’,
MASTER_LOG_FILE=‘mysql-bin.具体数字’,MASTER_LOG_POS=具体值;
3|6测试双主双从
在Master1创建数据库testdb
其他三个数据库刷新查询出现testdb数据库
在Master2创建user表
其他上数据库刷新出现user表
以上是关于mysql主从复制原理及一主一从搭建过程—2023.04的主要内容,如果未能解决你的问题,请参考以下文章
mysql之 mysql 5.6不停机主从搭建(一主一从基于GTID复制)