为了保障数据的安全与稳定性,我们常用数据库的主从复制与主主复制来实现。主从复制为从机实时拷贝一份主机的数据,当主机有数据变化时,从机的数据会跟着变,当从机数据有变化时,主机数据不变;同样地,主主复制就是,多个主机之间,只要有一个主机的数据变化了,其它主机数据也会跟着变化。
创新互联公司是一家集网站建设,定西企业网站建设,定西品牌网站建设,网站定制,定西网站建设报价,网络营销,网络优化,定西网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
添加以下内容
如果你是使用我之前那种方式启动的MySQL,那么你只需要去你相关联的宿主机的配置文件夹里面去建立一个 my.cnf 然后写入上面的类容就好了。
比如:我的启动命令如下(不应该换行的,这里为了方便查看,我给它分行了)
那么我只需要在 /docker/mysql_master/conf 这个目录下创建 my.cnf 文件就好了。
这个命令是需要在容器里面执行的
docker重启mysql会关闭容器,我们需要重启容器。
确保在主服务器上 skip_networking 选项处于 OFF 关闭状态, 这是默认值。 如果是启用的,则从站无法与主站通信,并且复制失败。
我的命令如下
在从服务器配置连接到主服务器的相关信息 (在容器里面的mysql执行)
上面代码的xxxxx你需要换成你的IP,docker 查看容器 IP 的命令如下:
启动的那个从服务器的线程
测试的话,你可以在主服务器里面,创建一个数据库,发现从服务器里面也有了,就成功了。
如果你还想要一个从服务器,那么你只需要按照上面配置从服务器再配置一个就行了,新建的从服务器,会自动保存主服务器之前的数据。(测试结果) 如果你上面的主从复制搞定了,那么这个主主复制就很简单了。我们把上面的从服务器也改成主服务器
1)、修改上面的从服务器的my.cnf文件,和主服务器的一样(注意这个server-id不能一样)然后重启服务器 2)、在从服务器里面创建一个复制用户创建命令一样(这里修改一下用户名可以改为 repl2) 3)、在之前的主服务器里面运行下面这个代码
上面主要是教你怎么搭建一个MySQL集群,但是这里面还有很多其它的问题。也是我在学习过程中思考的问题,可能有的小伙伴上来看到文章长篇大论的看不下去,只想去实现这样一直集群功能,所以我就把问题写在下面了。
1)、MySQL的replication和pxc MySQL的集群方案有replication和pxc两种,上面是基于replication实现的。
replication: 异步复制,速度快,无法保证数据的一致性。 pxc: 同步复制,速度慢,多个集群之间是事务提交的数据一致性强。
2)、MySQL的replication数据同步的原理 我们在配置的时候开启了它的二进制日志,每次操作数据库的时候都会更新到这个日志里面去。主从通过同步这个日志来保证数据的一致性。
3)、可否不同步全部的数据 可以配置,同步哪些数据库,甚至是哪些表。
4)、怎么关闭和开始同步
5)、我就我的理解画出了,主从、主从从、主主、复制的图。
往期推荐:
利用Docker仅花1分钟时间安装好MySQL服务
Linux下MySQL 5.7的离线与在线安装(图文)
Linux下安装MySQL8.0(收藏!)
MySQL 主从一直是面试常客,里面的知识点虽然基础,但是能回答全的同学不多。
比如楼哥之前面试小米,就被问到过主从复制的原理,以及主从延迟的解决方案,因为回答的非常不错,给面试官留下非常好的印象。你之前面试,有遇到过哪些 MySQL 主从的问题呢?
所谓 MySQL 主从,就是建立两个完全一样的数据库,一个是主库,一个是从库, 主库对外提供读写的操作,从库对外提供读的操作 ,下面是一主一从模式:
对于数据库单机部署,在 4 核 8G 的机器上运行 MySQL 5.7 时,大概可以支撑 500 的 TPS 和 10000 的 QPS, 当遇到一些活动时,查询流量骤然,就需要进行主从分离。
大部分系统的访问模型是读多写少,读写请求量的差距可能达到几个数量级,所以我们可以通过一主多从的方式, 主库只负责写入和部分核心逻辑的查询,多个从库只负责查询,提升查询性能,降低主库压力。
MySQL 主从还能做到服务高可用,当主库宕机时,从库可以切成主库,保证服务的高可用,然后主库也可以做数据的容灾备份。
整体场景总结如下:
MySQL 的主从复制是依赖于 binlog 的,也就是记录 MySQL 上的所有变化并以二进制形式保存在磁盘上二进制日志文件。
主从复制就是将 binlog 中的数据从主库传输到从库上,一般这个过程是异步的,即主库上的操作不会等待 binlog 同步的完成。
详细流程如下:
当主库和从库数据同步时,突然中断怎么办?因为主库与从库之间维持了一个长链接,主库内部有一个线程,专门服务于从库的这个长链接的。
对于下面的情况,假如主库执行如下 SQL,其中 a 和 create_time 都是索引:
我们知道,数据选择了 a 索引和选择 create_time 索引,最后 limit 1 出来的数据一般是不一样的。
所以就会存在这种情况:在 binlog = statement 格式时,主库在执行这条 SQL 时,使用的是索引 a,而从库在执行这条 SQL 时,使用了索引 create_time,最后主从数据不一致了。
那么我们改如何解决呢?
可以把 binlog 格式修改为 row,row 格式的 binlog 日志记录的不是 SQL 原文,而是两个 event:Table_map 和 Delete_rows。
Table_map event 说明要操作的表,Delete_rows event用于定义要删除的行为,记录删除的具体行数。 row 格式的 binlog 记录的就是要删除的主键 ID 信息,因此不会出现主从不一致的问题。
但是如果 SQL 删除 10 万行数据,使用 row 格式就会很占空间的,10 万条数据都在 binlog 里面,写 binlog 的时候也很耗 IO。但是 statement 格式的 binlog 可能会导致数据不一致。
设计 MySQL 的大叔想了一个折中的方案,mixed 格式的 binlog,其实就是 row 和 statement 格式混合使用, 当 MySQL 判断可能数据不一致时,就用 row 格式,否则使用就用 statement 格式。
有时候我们遇到从数据库中获取不到信息的诡异问题时,会纠结于代码中是否有一些逻辑会把之前写入的内容删除,但是你又会发现,过了一段时间再去查询时又可以读到数据了,这基本上就是主从延迟在作怪。
主从延迟,其实就是“从库回放” 完成的时间,与 “主库写 binlog” 完成时间的差值, 会导致从库查询的数据,和主库的不一致 。
谈到 MySQL 数据库主从同步延迟原理,得从 MySQL 的主从复制原理说起:
总结一下主从延迟的主要原因 :主从延迟主要是出现在 “relay log 回放” 这一步,当主库的 TPS 并发较高,产生的 DDL 数量超过从库一个 SQL 线程所能承受的范围,那么延时就产生了,当然还有就是可能与从库的大型 query 语句产生了锁等待。
我们一般会把从库落后的时间作为一个重点的数据库指标做监控和报警,正常的时间是在毫秒级别,一旦落后的时间达到了秒级别就需要告警了。
解决该问题的方法,除了缩短主从延迟的时间,还有一些其它的方法,基本原理都是尽量不查询从库。
具体解决方案如下:
在实际应用场景中,对于一些非常核心的场景,比如库存,支付订单等,需要直接查询从库,其它非核心场景,就不要去查主库了。
两台机器 A 和 B,A 为主库,负责读写,B 为从库,负责读数据。
如果 A 库发生故障,B 库成为主库负责读写,修复故障后,A 成为从库,主库 B 同步数据到从库 A。
一台主库多台从库,A 为主库,负责读写,B、C、D为从库,负责读数据。
如果 A 库发生故障,B 库成为主库负责读写,C、D负责读,修复故障后,A 也成为从库,主库 B 同步数据到从库 A。
在MySQL中,可以使用多种存储引擎。其中最常用的InnoDB引擎支持事务,Redo Log和Undo Log就是InnoDB里面的工具,用于实现事务。而Binlog是MySQL层面的东西,用于实现主从复制,与使用的存储引擎无关。
通过监听并解析Mater的Binlog,也可以实现将MySQL中的数据同步到其他应用组件中(比如更新缓存)的效果。
在不发生宕机的情况下,未提交的事务和已回滚的事务是不写入Binlog日志中的,只有提交成功的事务才写入Binlog日志。这一点和Redo Log不一样,Redo Log中会记录未提交、已回滚的事务内容。
Binlog是一种逻辑日志——例如Binlog的statement格式记录原始SQL语句、RAW格式记录某一行修改前后的值——且一个事务的日志在Binlog中是连续排列的,因此要求每个事务都要串行地写入,这意味着每个事务在写Binlog之前都要排他地锁住Binlog,这会导致写的效率很低。MySQL5.6之后,通过pipline技术异步地批量化将已提交的事务内容写入Binlog。
一个事务的提交既要写Binlog日志又要写Redo Log日志,如何保证双写的原子性?一个写成功,写另外一个时发生宕机,重启后如何处理?在讨论这个问题之前,先说下Binlog自身写入的原子性问题:Binlog刷盘到一半,出现宕机,这个问题和Redo Log的写入原子性是同样的问题,通过类似于checksum的办法或者Binlog中的结束标记来判断出某个事务的Binlog这是不是不完整的Binlog,从而把不完整的部分截掉。对于客户端来说,此时宕机,事务肯定是没有提交成功的,所以截掉也没问题。下面来讲如何保证双写Binlog和Redo Log的原子性。由于双写Binlog和Redo Log发生在同一台机器上,这其实是一个内部分布式事务,可以使用两阶段提交法来实现双写的原子性。简单来说就是:
1)第一阶段(准备阶段):MySQL Server要求innoDB完成将事务内容写入Redo Log中的工作,只等事务提交;以及,MySQL Server完成Binlog内容写入内存的工作,只等刷盘。两个都准备好之后,会向MySQL Server发送OK反馈,MySQL Server紧接着执行第二阶段。
2)第二阶段(提交阶段):收到客户端的Commit指令,MySQL Server先将内存中的Binlog刷盘,然后让innoDB执行事务的提交。两个都完成之后,会向MySQL Server发送OK反馈,两阶段提交结束。
若双写Binlog和Redo Log的过程中发生宕机,处理思路为:
1)若宕机发生在第一阶段,此时Binlog还在内存中,宕机导致全部消失。而Redo Log记录了未提交的日志,MySQL Server重启后感知到Binlog中不存在Redo Log中记录的未提交事务,会自行回滚未提交事务的Redo Log日志;
2)若宕机发生在第二阶段,Binlog写了一半,innoDB还未执行提交,MySQL Server重启后会对Binlog做截断,对Redo Log中记录的未提交事务做回滚;
3)若宕机发生在第二阶段,Binlog写入成功,innoDB还未执行提交,MySQL Server重启后会通过checksum的办法或者Binlog中的结束标记感知到Binlog写入成功,紧接着对Binlog中存在的、但Redo Log未提交的事务发起提交。
在MySQL的Master / Slave集群模式中,有三种主从复制模式:
1)同步复制:所有的Slave都收到Master发送的Binlog,并且接收完,Master才认为事务提交成功,再对客户端返回成功。这种方式最安全,但是性能很差;
2)异步复制:只要Master事务提交成功,就对客户端返回成功。后台线程异步地将Binlog发送给Slave,然后Slave回放Binlog。这种方式性能最好,但是可能会导致数据丢失;
3)半同步复制:Master事务提交后,同时把Binlog同步给Slave,只要有部分(数量可以配置)Slave收到了Binlog,就认为事务提交成功,对客户端返回。
对于半异步复制,如果Slave超时后还未返回,也会退化为异步复制。所以无论是异步复制还是半异步复制,都无法严格保证主从中的数据完全一致,主从复制的延迟会导致主节点宕机后部分数据未来得及同步到从节点,从而丢失数据。但是主节点宕机后,还是要立即切换到从节点,保证服务的可用(牺牲一致性保证可用性),数据的丢失可以通过后续的人工干预来补偿。