主从复制实战的服务器是我在腾讯云官网上购买的几台云服务器进行操作的,不得不说云是一个好东西,以前都是在centos上进行模拟,现在在云服务器上模拟感觉对自己的提升更大。这里想强调一下,如果是在云服务器上模拟主从复制,尽量选海外的服务器,因为在下载mysql的时候国内服务器真的特别慢,海外服务器速度会快很多。现在开始进入正题。
(1)主从复制技术介绍
主从复制是Mysql数据库的一种容灾备份方案,是Mysql自带的功能,无需借助第三方工具,Mysql的主从复制并不是数据库磁盘上的文件直接拷贝,而是通过逻辑的binlog日志复制到要同步的服务器本地,然后由本地的线程读取日志里面的SQL语句重新应用到Mysql数据库中。

(2)Mysql主从复制的常用拓扑结构
Mysql数据库支持单向、双向、链式级联、环状等不同业务场景的复制。在复制过程中,一台服务器充当主服务器(Master),接收来自用户的内容更新,而一个或多个其他服务器充当从服务器(Slave),接收来自主服务器Binlog文件的日志内容,解析出SQL重新更新到从服务器,使得主从服务器数据达到一致。
推荐使用单向,双向和级联。

(3)Mysql主从复制工作流程
复制一个分为三大步骤:
1.master将改变记录到二进制日志(binary log)中,这些记录叫做二进制日志事件(binary log events)
2.slave将master的binary log events拷贝到它的中继日志(relay log)中;
3.slave重做中继日志中的事件,将日志操作还原并生成数据。

写数据访问的是主服务器,让会话线程进行增删改数据改变,当数据改变事务提交后就会以串行的方式写入二进制日志文件,此时从库有一个IO线程会去读取主库的二进制日志文件,在二进制日志文件中有一个dump线程,这个dump线程会把二进制日志文件的内容dump下来传给IO线程,IO进程主要就是从二进制日志中读取事件(接受的单位是事件event),如果已经跟上master主机的数据(也就是没数据发生改变),则IO线程会睡眠等待master产生新的事件。如果有不同,IO线程会把不同写到中继日志中。然后SQL线程去读中继日志(是SQL去读哈)然后重新执行到从服务器中,所以SQL线程就是把中继日志进行回放还原并应用到本地数据库中。
所以主从复制,主要是从库主动去主库去取,最重要的就是IO线程和SQL线程。中继日志通常会位于OS的缓存中,所以中继日志开销很小。所以一共四个线程。

(4)Mysql主从复制技术的同步方式
一共有四种。(以下图片出自网上)
传统半同步复制:在半同步复制中,master写数据到binlog且sync,且commit,虽然commit但是并不把结果返回给客户,而是一直等待ACK。当至少一个slave request bilog后写入到relay-log并flush disk,就返回ack(不需要回放完日志)。性能、功能都介于异步和全同步中间,目的是为了折中上述两种架构的性能以及优缺点。

无损复制(增强版的半同步复制):在半同步复制中,master写数据到binlog且sync,然后一直等待ACK. 当至少一个slave request bilog后写入到relay-log并flush disk,就返回ack,然后主才Commit保证数据一定备份了,然后再把结果返回给客户。增强版的半同步复制,数据零丢失,性能好。


异步复制:master写数据到binlog然后comiit,同时sync(让slave的io线程去dump),slave request binlog后写入relay-log并flush disk(刷新到磁盘)。MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。搭建简单,使用广泛,但是异步所以有丢失数据库风险,因为master挂掉后,slave可能会丢失事务。

全同步复制:master写数据到binlog且sync,然后commit,commit后主进入等待,当所有的从库slave request binlog后写入relay-log并flush disk,并且回放完日志后再返回ack给主,主才把结果返回给客户。也就是指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。优点保证数据安全,不丢失数据,缺点损失性能。

(5)Mysql主从复制技术的GTID特性
GTID:对于一个已提交事务的编号,事务的唯一编号,并且是一个全局唯一编号。GTID和事务会记录到binlog中,用来标识事务。GTID是用来替代以前传统复制方法(binlog+position日志点)。Mysql支持GTID后,一个事务在集群中就不再孤单,在每一个节点中,如果存在具有相同标识符的情况,可以避免同一个事务在同一个节点中出现多次的情况(也就是说以前是认某个日志的某个点,现在是认某个日志里某个点做的事)。
GTID的出现最直接的效果就是:对每一个事务在集群中具有了唯一性的意义,相对于行复制来讲数据安全性更高,故障切换更简单。因为事务定义的越来越明晰,行复制针对的是内容复制。
GTID是由server_uuid:Sequence_Number组成。而server_uuid是一个Mysql实例的全局唯一标识,存放在$datadir/auto.cnf中。而Sequence_Number是Mysql内部的一个事务编号。一个Mysql实例是不会有重复的序列号的(保证服务器内唯一),所以这个也表示在该实例上已经提交事务的数量,并且随着事务提交而递增。
根据GTID可以知道事务最初是在哪个实例上提交的,方便故障排查和切换。
Gtid是mysql5.6之后才出现的,如果现在我一个mysql8.0的从库去多源复制一群5.5的主库,就不能用gtid来实现全局的id,所以这个时候就要做一个需求,做到流式备份。
关于GTID更多的讲解,会在之后专门出一篇文章进行阐述。

(6)环境搭建
(主机和从机皆为腾讯云购买的服务器,文章中ip不是真实ip,进行了修改)
主机:172.26.0.16 3306端口
从机:172.26.0.12 3306端口
主库用于生产,从库用于数据容灾和主库备机。
第一步:
在主机和从机中 vi /etc/hosts加入主机和从机名方便识别。

第二步:两台机器都安好Mysql数据库可以访问。

(7)Mysql主从复制重要参数
1.基本参数
基本参数:bing-address = 172.26.0.16 绑定地址
服务器id:server_id=163306 主从不相同,规范建议:后IP+端口
跳过主机名/域名解析:skip_name_resolve = off 默认是关闭的
事务隔离级别:transaction-isolation = read-committed 设置为读已提交

2.关于binlog二进制日志参数
log_bin=/mysql/log/3306/binlog/itpuxdb-binlog 二进制路径放的位置
log_bin_index=/mysql/log/3306/binlog/itpuxdb-binlog.index 二进制索引放的位置
binlog_format=row (必须)二进制日志文件格式 一定是行
binglog_rows_query_log_events=on 二进制日志中记录更详细的SQL操作
sync_binlog = 1 默认,mysql每次提交事务之前会将二进制同步到磁盘上,保证服务器崩溃时不会丢失事件(同步日志)
innodb_flush_log_at_trx_commit = 1 默认,每次事务提交时Mysql都会把log buffer(日志缓存)的数据写入log file(日志文件),并且flush(刷到磁盘)中去。保证数据安全。

3.其他参数
log_bin_trust_function_creators=1 默认为0,为1是同步函数和存储过程
max_binlog_size = 2048M 最大日志大小,默认为1024M
expire_logs_days = 7 binlog保留多少天,看具体安排
binlog_cache_size = 1M 默认32K,binlog缓存的大小,设置时要当心,建议1~4M,根据业务情况。
innodb_support_xa=1 这个参数是在主库上设置的,默认是自动开启。看到xa首先想到的是分布式事务,这个参数确保事务日志写入bin-log的顺序与事务的time-line是一致的,这样在系统奔溃的时候,启用日志恢复,可以严格按照时间线来恢复数据库。

4.关于relay_log中继日志参数
relay_log = /mysql/log/3306/relaylog/itpuxdb-relay.log 中继日志的路径放在哪里

relay-log-recover = 1 针对的是IO线程安全的,这是打开repication中继日志奔溃恢复模式,replication支持中继日志的自我修复功能。当slave从库宕机后,如果replay-log发生损坏,导致一部分中继日志没有处理,就自动放弃未执行的replay-log,重新从master上获取日志,继续完成中继日志的恢复。也就是说该参数表示当前接收到的relay-log全部删除,然后从SQL线程回放到的位置重新拉取。

relay_log_info_repository=table 针对的是SQL线程安全的,默认是file(SQL执行情况存放在文件中),SQL线程的数据回放是写数据库操作,而relay-info是写文件操作,这两个操作很难保证一致性。所以用table表的形式来记录SQL线程的执行情况,把执行的中继日志消息relay-info将写入到mysql.slave_relay_log_info这张表中

master_info_repository = table 默认是file(也就是把IO线程执行情况放在文件中),IO线程也是接收一个个的event,所以这个参数的作用是将接收到的event通过设置参数master_info_repository可以将master-info信息写到什么位置,设置为table则把信息写到表中,性能上比设置为FILE有很高的的提升,可靠性也得到保证,设置为table后,master-info将信息保存到mysql.salve_master_info

5.关于同步方式的参数(如果不加这些就默认异步同步)
半同步复制(Mysql5.6的方法):
loose_rpl_semi_sync_master_enabled = 1 开启主的半同步复制
loose_rpl_semi_sync_slave_enabled = 1 开启从的半同步复制
loose_rpl_semi_sync_master_timeout = 5000 超时5秒,切回异步

半同步和无损复制开启(Mysql5.7方法,AFTER_SYNC和AFTER_COMMIT选一个):
rpl_semi_sync_master_wait_for_slave_count=1 至少收到1个slave发回的ack
rpl_semi_sync_master_wait_point=AFTER_SYNC 开启无损复制
rpl_semi_sync_master_wait_point=AFTER_COMMIT 开启半同步复制

6.关于GTID的参数
gtid_mode = on 打开gtid的模式
log_slave_updates = 1
enforce_gtid_consistency = 1

gtid_mode:打开gitd的模式有下面几种
on:产生GTID,slave只接收带GTID的事务
ON_PERMISSIVE:产生GTID,slave接受不带GTID事务也接受带GTID的事务
OFF:不产生GTID,slave只接受不带参GTID的事务
OFF_PERMISSIVE:不产生GTID,slave接受不带GTID事务也接受带GTID的事务。

log_slave_updates:
当从库log_slave_updates参数没有开启时,从库的binlog不会记录来源于主库的操作记录。只有开启log_slave_updates,从库binlog才会记录主库同步的操作日志。如果是多个从库,切换后,建议关掉log_slave_updates参数,否则重置成主库以后,可能会将已经执行过的二进制日志重复传送给S2(从库),导致S2(从库)同步错误。

enforce_gtid_consistency:
on:当发现语句/事务不支持GTID时,返回错误信息
WARN:当发现不支持语句/事务,返回警告,并且日志中记录警告信息
OFF:不检查是否有GTID不支持的语句/事务

(8)Mysql主从复制实战
第一步:准备主从二进制与中继日志目录
mkdir -p /mysql/log/3306/binlog 主库创建二进制日志
mkdir -p /mysql/log/3306/relaylog 备库中继日志
chown -R mysql:mysql /mysql/log/3306/binlog 下面修改权限
chown -R mysql:mysql /mysql/log/3306/relaylog
chmod -R 775 /mysql/log/3306/binlog
chmod -R 775 /mysql/log/3306/relaylog

第二步:准备主库参数 在vi /etc/my.cnf中添加(记住日志位置)
bind-address= 172.26.0.16 主库ip
server_id=163306 唯一serverid
skip_name_resolve = ON
expire_logs_days = 7
binlog_cache_size = 1M
max_binlog_size = 2048M
log_bin_trust_function_creators = 1
innodb_flush_log_at_trx_commit =1
sync_binlog = 1

transaction-isolation = READ-COMMITTED
gtid_mode = ON
enforce_gtid_consistency = 1
log-slave-updates = 1
binlog_gtid_simple_recovery=1
//下面的这四行就是开启二进制日志格式
log_bin=/mysql/log/3306/binlog/itpuxdb-binlog
log_bin_index=/mysql/log/3306/binlog/itpuxdb-binlog.index
binlog_format=ROW
binlog_rows_query_log_events=on

//配置无损同步配置
plugin_dir= /usr/local/mysql/lib/plugin/
plugin_load =
“rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so”
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000
rpl_semi_sync_master_wait_point = AFTER_SYNC
rpl_semi_sync_master_wait_for_slave_count = 1

然后重启systemctl restart mysqld开是否生效。

第三步:准备从库
bind-address= 172.26.0.12
server_id=123306
skip_name_resolve = ON
expire_logs_days = 7
binlog_cache_size = 1M
max_binlog_size = 2048M
log_bin_trust_function_creators = 1
innodb_flush_log_at_trx_commit =1
sync_binlog = 1

transaction-isolation = READ-COMMITTED
gtid_mode = ON
enforce_gtid_consistency = 1
log-slave-updates = 1
//二进制日志
binlog_gtid_simple_recovery=1
log_bin=/mysql/log/3306/binlog/itpuxdb-binlog
log_bin_index=/mysql/log/3306/binlog/itpuxdb-binlog.index
binlog_format=ROW
binlog_rows_query_log_events=on
//中继日志
relay_log = /mysql/log/3306/relaylog/itpuxdb-relay.log
read_only=1

//无损同步
plugin_dir=/usr/local/mysql/lib/plugin/
plugin_load =
“rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so”
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000
rpl_semi_sync_master_wait_point = AFTER_SYNC
rpl_semi_sync_master_wait_for_slave_count = 1

配置好后,重启主从数据库,没有异常则正确。

第四步:主从库创建复制用户并授权
mysql -uroot -prootroot
create user ‘repuser’@’%’ identified with mysql_native_password BY ‘repuser123’;
grant replication client,replication slave on . to ‘repuser’@’%’;
flush privileges;
select user,host from mysql.user;

这个用户是repuser。首先进入mysql数据库并创建一个用户repuser,密码是repuser123,然后授权replication client和replication slave就是主从数据库*.*的所有数据库和对象到repuser这个用户,然后flush刷新权限。这个步骤主从库都要去做。

第五步:在从库上使slave与master建立连接

mysql -uroot -p******
stop slave;
reset master;
reset slave;
change master to
master_host=’ 172.26.0.16’, //从库连得主机
master_port=3306, //端口
master_user=‘repuser’, //连主库用户
master_password=‘repuser123’, //连主库密码
master_auto_position=1; //自动开始

上面这个就是开启gitd这个功能。

第六步:主从同步
start slave; //运行从库
show slave status \G //查看状态命令
SHOW PROCESSLIST; //看进程线程

当红色框的为yes后,就成功了。

第七步:数据验证,看是否同步了。
主库:
create database itpuxdb1;
create user ‘itpux0’@’%’ identified with mysql_native_password by ‘itpux01’;
grant all privileges on itpuxdb1.* to ‘itpux0’@’%’;
flush privileges;

use itpuxdb1;
create table itpuxbak11 (id int,name varchar(40));
insert into itpuxbak values
(1,‘itpux111’),(2,‘itpux112’),(3,‘itpux113’),(4,‘itpux114’),(5,‘itpux115’);
commit;
select * from itpuxbak11;

备库检查:
mysql -uitpux0 -pitpux01
select * from itpuxdb1.itpuxbak11;
insert into itpuxdb1.itpuxbak11 values (6,‘itpux116’);
mysql -uroot -prootroot
show slave status \G
show processlist;

因为从库设置了read_only=1,所以只能读。但是如果你是用超级管理员root登录的,那么从机也可以插入。之后要使用只需要操作从机就可以了,start slave。

第八步:如果想设置互为主从,则首先双方停掉stop slave
先在b机器show master status;查看file和position字段的值;然后在a机器中设置:
change master to
master_host=‘172.26.0.16’,
master_port=3306,
master_user=‘repuser’,
master_password=‘repuser123’,
master_auto_position=0,
master_log_file=’ itpuxdb-binlog.000001’, //b机器的file
master_log_pos=155; //b机器的pos

change master to
master_host=‘172.26.0.12’,
master_port=3306,
master_user=‘repuser’,
master_password=‘repuser123’,
master_auto_position=0,
master_log_file=‘itpuxdb-binlog.000002’,
master_log_pos=55989;

然后start slave。
然后再a机器中show master status;查看file和position字段的值;然后在b机器中设置:
change master to
master_host=‘172.26.0.12’,
master_port=3306,
master_user=‘repuser’,
master_password=‘repuser123’,
master_auto_position=0,
master_log_file=‘itpuxdb-binlog.000001’,
master_log_pos=155;

然后再slave sstart就可以了。

(9)主从同步延迟
之所以会造成主从同步延迟,主要原因是从库是以单线程的形式去读取主库写操作的binlog,当主库的TPS(每秒事务量)并发较高时,产生的DDL数量了超过slave一个sql线程所能承受的范围:
①主库针对写操作,顺序写binlog,主库对所有的DDL和DML在binlog中都是顺序写,效率高,只有当主库事务commit后从库才去读取binlog进行同步,如果主库一个事务执行了一分钟,那么延迟就出来了。

②其次,从库的Slave_SQL_Running线程读取binlog在本地原样执行是随机写,这样成本高很多,就可能在slave的其他查询上产生lock争用,而且Slave_SQL_Running是单线程的,当一个DDL卡住了要执行10分钟,那么所有之后的DDL也会等待这个DDL执行完二次可以继续执行,就导致了延迟。而对于这个卡住的DDL在主库上其实也会卡,但因为主库可以并发执行,而从库单线程不可以,所以slave会延迟。

DDL:创建数据库中的各种对象-----表、视图、索引
DML:insert、update、delete

对于主从同步延迟的解决:
对于ddl而言,可以采用一个online DDL的方式,也就是在线ddl:也就是新建一个表,这个表有两个操作,一个是拷存量(就是把原始表的数据通过replace的方式插入新表),第二个是添增量(就是模拟自己是一个从库,然后添加原始表更改添加的数据),最后锁表1秒钟用来进行表重命名。这些步骤在执行的过程中从表也在跟着执行,所以从表也会有一张这种表,从而解决DDL的延迟问题。
对于DML而言,就是主库多个事务并发执行的情况,在Mysql5.6之后可以设置slave_parallel_workers参数来实现并行复制,也就是在从库中创建slave_parallel_workers设置的参数那么多个worker空间,从库会把读取到主库的binlog里的数据放到这些worker空间中并行执行。

Mysql主从复制集群配置与实战相关推荐

  1. 使用docker compose部署MySQL主从复制集群

    使用docker compose部署MySQL主从复制集群 环境说明 宿主机:Ubuntu 14.04.6 LTS Docker Engine: 18.06.3-ce docker compose: ...

  2. redis+主从复制+集群配置

    redis+主从复制+集群配置 redis是一个key-value存储系统.和memcached类似,不过redis支持的value类型更多,主要有:string(字符串).list(链表).set( ...

  3. docker mysql日志写入本地_Docker Compose搭建MySQL主从复制集群

    转载自https://zhuanlan.zhihu.com/p/45193580 前言 随着应用业务数据不断的增大,应用的 响应速度不断下降,在检测过程中我们不难发现大多数的请求都是 查询操作.此时, ...

  4. Docker学习总结(43)——Docker Compose 搭建Mysql主从复制集群

    前言 随着应用业务数据不断的增大,应用的 响应速度不断下降,在检测过程中我们不难发现大多数的请求都是 查询操作.此时,我们可以将数据库扩展成 主从复制模式,将 读操作 和 写操作 分离开来,多台数据库 ...

  5. CentOS服务器Mysql主从复制集群的搭建

    在配置Mysql数据库主从复制集群的时候要保证: 1.主从服务器操作系统版本和位数一致. 2.Mysql版本一致. 为了保证稳定性,最好服务器操作系统和Mysql数据库环境一致. CentOS服务器上 ...

  6. mysql galera集群配置

    环境配置 我们在每个节点上都做如下配置: 关闭selinux setenforce 0 sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/seli ...

  7. quartz mysql 表 集群配置_Spring整合实战丨Quartz 集群配置

    Quartz说明 1.quartz可以通过jdbc直连连接到MYSQL数据库,读取配置在数据库里的job初始化信息,并且把job通过java序列化到数据库里,这样就使得每个job信息得到了持久化,即使 ...

  8. 使用docker部署mysql主从复制集群

    一.环境搭建 虚拟机环境:centos7 IP:192.168.37.134 用户名:root 密码:123 启动3个容器,一个是master,端口是3307,另外两个是slaver,端口是3308和 ...

  9. Mysql主从复制集群类型和搭建方法

    概述 单机Mysql的缺点: 读写请求都落在一台机器上,压力较大. 低可用性,因为是单机单节点,一旦该节点挂了,服务就对外不可用了. 容灾性低,因为单机,如果没有做及时备份的话,一旦机器出现不可挽回灾 ...

最新文章

  1. ffmpeg architecture(上)
  2. GroovyQ | 关注Groovy社区动态,分享Groovy开发经验。
  3. 基于DPI(深度报文解析)的应用识别
  4. 【Android 逆向】Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
  5. 老的消息中间件投递失败的类型值_图文结合了解一下Java消息中间件的概述
  6. 手机点餐系统概述_疫情之下,无接触点餐模式再成热搜,扫码点餐系统能不能普及?...
  7. 计蒜客 2019 蓝桥杯省赛 B 组模拟赛(一)
  8. MariaDB 10.3 instant ADD COLUMN亿级大表毫秒级加字段
  9. 生存的关键往往在于偶然的机遇——李光耀
  10. idea导入本地idea的web项目(服务器用的是tomcat)
  11. 非常经典的C语言知识点总结!
  12. 论文笔记:主干网络——SENet
  13. android涂鸦程序(在图像上绘制)
  14. 计算机管理用房设置要求,综合医院建筑规范(放射科用房)
  15. Flash和XML实现电子地图查询及定位功能
  16. 点开瞅瞅,再来几道Python面试题吧,Python面试题No20
  17. Nginx1.6.2版本安装遇到的坑以及配置反向代理
  18. 01.软件测试基础知识整合
  19. AD 原理图层次化画图
  20. COGS——T 1786. 韩信点兵

热门文章

  1. 【无人驾驶二】GPS及惯性传感器在无人驾驶中的应用
  2. 查询平均工资最低的部门信息
  3. Linux下使用RAW SOCKET原始套接字构造UDP原始数据帧广播到局域网,在局域网的另一台计算机上显示UDP发送的信息
  4. python二维数组去重_np.unique()对一维和二维数组去重
  5. SQL Server多语句表值函数
  6. 【安全硬件】Chap.5 如何检测芯片中硬件木马?硬件木马的类型有哪些?检测硬件木马的技术
  7. 微星msi GS66黑苹果安装引导包(OpenCore for macOS Monterey)
  8. 单片机包络检波c语言,模拟电子系统设计指南:从半导体、分立元件到TI集成电路的分析与实现(基础篇)...
  9. 有关channel的相关知识(2)
  10. 数字媒体技术专业延伸方向——特效