mysql 主从备份原理
mysql 主从备份原理
用途及条件
mysql主从复制用途
- 实时灾备,用于故障切换
- 读写分离,提供查询服务
- 备份,避免影响业务
主从部署必要条件:
- 主库开启binlog日志(设置log-bin参数)
- 主从server-id不同
- 从库服务器能连通主库
主从原理
master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时,则将其改变写入二进制日志中;slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,
当master服务器数据发生变化,则slave开始一个I/O Thread请求master二进制事件,同时maser节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志Relay_Log_File中,从节点将启动SQL Thread从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/O Thread和SQL Thread将进入睡眠状态,等待下一次被唤醒。
需要注意的是:
-
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两节点间时间需同步
主从切换
在状态 1 中,客户端的读写都直接访问节点 A,而节点 B 是 A 的备库,只是将 A 的更新都同步过来,到本地执行。这样可以保持节点 B 和 A 的数据是相同的。当需要切换的时候,就切成状态 2。这时候客户端读写访问的都是节点 B,而节点 A 是 B 的备库。
在状态 1 中,虽然节点 B 没有被直接访问,但是我依然建议你把节点 B(也就是备库)设置成只读(readonly)模式。这样做,有以下几个考虑:
- 有时候一些运营类的查询语句会被放到备库上去查,设置为只读可以防止误操作;
- 防止切换逻辑有 bug,比如切换过程中出现双写,造成主备不一致;
- 可以用 readonly 状态,来判断节点的角色。
有同学想,我把从库设置成只读了,还怎么跟主库保持同步更新呢?这个问题,你不用担心。因为 readonly 设置对超级 (super) 权限用户是无效的,而用于同步更新的线程,就拥有超级权限。
主从延迟的原因
主从主机的性能不一样
更新请求对 IOPS 的压力,在主库和从库上是无差别的,从的机器性能比主的机器差时,当从库主机上的多个从库都在争抢资源的时候,就可能会导致主从延迟
从的主机读压力较大
我们作了主从读写分离,开发写的代码执行大量读的查询时,对从压力较大,导致从的cpu或者内存占用很高,导致主从延迟,可以一主多从来解决,但是不宜过多,一般3-5个从,过多的从也会导致主从延迟同步
网络原因
主和从的机器不在同一台机房,网络传输数据较慢导致的主从延迟
大事务
主库上必须等事务执行完成才会写入 binlog,再传给备库。所以,如果一个主库上的语句执行 10 分钟,那这个事务很可能就会导致从库延迟 10 分钟
时间不同步
主从时间不一致
mysql8主从搭建
环境准备
master 192.168.1.110
slave 192.168.1.120
基础配置
//临时关闭selinux
setenforce 0
//永久关闭
vi /etc/sysconfig/selinux
SELINUX=disabled
//关闭防火墙
systemctl stop firewalld
systemctl stop iptables
//时间同步
//安装chrony
yum install chrony
//修改配置文件
vi /etc/sysconfig/selinux
server ntp1.aliyun.com iburst
//启动服务
systemctl start chronyd
master主节点配置
vim /etc/my.cnf
[mysqld]
#数据库唯一ID,主从的标识号绝对不能重复。
server-id=1
#开启bin-log,并指定文件目录和文件名前缀
log-bin=mysql-bin
#同步test数据库。如果同时同步多个库,就以此格式另写几行即可。如果不指定某个库同步,删除此行,表示同步所有库(除了ignore忽略的库)
binlog-do-db=test
#不同步mysql系统数据库。如果是多个不同步库,就以此格式另写几行;也可以在一行,中间逗号隔开。
binlog-ignore-db=mysql
#设置二进制日志自动删除/过期的天数,避免占用磁盘空间。默认值为0,表示不自动删除。
expire_logs_days=7
#确保binlog日志写入后与硬盘同步
sync_binlog=1
#bin-log日志文件格式
binlog_format=ROW
注意:
-
在主服务器上最重要的二进制日志设置是sync_binlog,这使得mysql在每次提交事务的时候把二进制日志的内容同步到磁盘上,即使服务器崩溃也会把事件写入日志中。
-
sync_binlog这个参数是对于MySQL系统来说是至关重要的,他不仅影响到Binlog对MySQL所带来的性能损耗,而且还影响到MySQL中数据的完整性。对于"sync_binlog"参数的各种设置的说明如下:
-
sync_binlog=0,当事务提交之后,MySQL不做fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定什么时候来做同步,或者cache满了之后才同步到磁盘。
-
sync_binlog=n,当每进行n次事务提交之后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。
-
在MySQL中系统默认的设置是sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。而当设置为“1”的时候,是最安全但是性能损耗最大的设置。因为当设置为1的时候,即使系统Crash,也最多丢失binlog_cache中未完成的一个事务,对实际数据没有任何实质性影响。
-
从以往经验和相关测试来看,对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。
数据一致性
在同步前保证master和slave中的数据一致,新环境忽略本步骤
导出数据库之前先锁定数据库
#数据库只读锁定命令,防止导出数据库的时候有数据写入,unlock tables命令解除锁定
mysql> flush tables with read lock;
导出master数据库中需要同步的库
#导出需要同步的库
[root@master ~]#mysqldump -uroot test -p123456 >/opt/test.sql
#如不指定,则导出所有库
mysqldump -uroot -p123456 --all-databases>/opt/all.sql
将导出数据导入salve中
#传到slave
scp /opt/all slave:/opt
#在slave导入数据库
mysql> source /opt/all.sql
创建数据同步账号
登录主数据库创建一个用于从数据库复制的账号
mysql> create user 'slave'@'192.168.1.120' identified with mysql_native_password by 'slave';
grant replication slave on *.* to 'slave'@'192.168.1.120';
mysql> flush privileges;
查看主服务器master状态(注意File与Position项,从服务器需要这两项参数)
mysql> show master status;
+-----------+-----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------+-----------+--------------+------------------+-------------------+
| mysql-bin.000065 | 186607472 | | | |
+-----------+-----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
配置slave
修改my.cnf配置文件
vim /etc/my.cnf
#设置从服务器id,必须于主服务器不同
server-id=2
#启动MySQ二进制日志系统
log-bin=mysql-bin
#需要同步的数据库名。如果不指明同步哪些库,就去掉这行,表示所有库的同步(除了ignore忽略的库)
配置主从同步指令
#执行同步前,要先关闭slave
mysql> stop slave;
mysql> change master to master_host='192.168.1.110',master_user='slave',master_password='slave',master_log_file='ON.000065',master_log_pos=186607472;
mysql> start slave;
mysql> show slave status \G;
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.120
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: ON.000065
Read_Master_Log_Pos: 187730832
Relay_Log_File: xmkjoa02-relay-bin.000002
Relay_Log_Pos: 46151494
Relay_Master_Log_File: ON.000065
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 187730832
Relay_Log_Space: 46151706
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: Yes
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 6c3f5abb-1c32-11ec-96ba-fa163e7a46bf
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 1
Network_Namespace:
1 row in set (0.00 sec)
如上,当IO和SQL线程的状态均为Yes,则表示主从已实现同步了!