十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程,专门用于服务备库 B 的这个长连接。一个事务日志同步的完整过程是这样的:
站在用户的角度思考问题,与客户深入沟通,找到围场网站设计与围场网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都网站建设、成都网站制作、企业官网、英文网站、手机端网站、网站推广、域名申请、网站空间、企业邮箱。业务覆盖围场地区。
1、在备库 B 上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码,以及要从哪个位置开始请求 binlog,这个位置包含文件名和日志偏移量。
2、在备库 B 上执行 start slave 命令,这时候备库会启动两个线程,就是图中的 io_thread 和 sql_thread 。其中 io_thread 负责与主库建立连接。
3、主库 A 校验完用户名、密码后,开始按照备库 B 传过来的位置,从本地读取 binlog, 发给 B(push模式) 。
4、备库 B 拿到 binlog 后,写到本地文件,称为中转日志( relay log )。
5、sql_thread 读取中转日志,解析出日志里的命令,并执行。
这里需要说明,后来由于多线程复制方案的引入, sql_thread 演化成为了多个线程。
binlog 的三种格式对比:
一种是 statement,按语句进行数据备份,可能需要联系上下文,日志相对较少 ,一种是 row,按行记录对数据的修改,无需关心sql语句或者上下文,逻辑简单,日志文件巨大,性能相对较低 。还有第三种格式,叫作 mixed ,其实它就是前两种格式的 混合 。
show variables like ' binlog_format '; 该参数控制。
1、因为有些 statement 格式的 binlog 可能会导致主备不一致 ,所以要使用 row 格式。
2、但 row 格式的缺点是, 很占空间 。比如你用一个 delete 语句删掉 10 万行数据,用 statement 的话就是一个 SQL 语句被记录到 binlog 中,占用几十个字节的空间。但如果用 row 格式的 binlog,就要把这 10 万条记录都写到 binlog 中。这样做,不仅会占用更大的空间,同时写 binlog 也要耗费 IO 资源,影响执行速度。
3、MySQL 就取了个折中方案,也就是有了 mixed 格式的 binlog。mixed 格式的意思是,MySQL 自己会判断这条 SQL 语句是否可能引起主备不一致,如果有可能,就用 row 格式,否则就用 statement 格式。也就是说,mixed 格式可以利用 statment 格式的优点,同时又避免了数据不一致的风险。
越来越推荐row格式,因为它方便恢复数据 。
备库: show slave status\G 查看备库情况, seconds_behind_master 主备延时,理想状况为0.
1、机器异构,备库性能差或者集中在一个机器上。
2、忽视备库压力,对备库使用没有节制,比如复杂的读计算。
1、一主多从。除了备库外,可以多接几个从库,让这些从库来分担读的压力。
2、通过 binlog 输出到外部系统,比如 Hadoop 这类系统,让外部系统提供统计类查询的能力。
在主库上,影响并发度的原因就是各种锁了。
在备库上,就是图中备库上 sql_thread 更新数据 (DATA) 的逻辑。如果是用 单线程 的话,就会导致备库应用日志不够快,造成主备延迟。
官方 MySQL5.6 版本 ,支持了并行复制,只是支持的粒度是 按库并行 。这个策略的并行效果,取决于压力模型。如果在主库上有多个 DB,并且 各个 DB 的压力均衡 ,使用这个策略的效果会很好。
相比于 按表 和 按行 分发,这个策略有两个优势:
1、构造 hash 值的时候很快,只需要库名;而且一个实例上 DB 数也不会很多,不会出现需要构造 100 万个项这种情况。
2、不要求 binlog 的格式。因为 statement 格式的 binlog 也可以很容易拿到库名。
但是,如果你的主库上的表都放在同一个 DB 里面,这个策略就没有效果了;或者如果不同 DB 的热点不同,比如一个是业务逻辑库,一个是系统配置库,那也起不到并行的效果。
理论上你可以创建不同的 DB,把相同热度的表均匀分到这些不同的 DB 中,强行使用这个策略。不过据我所知,由于需要特地移动数据,这个策略用得并不多。
在 MariaDB 并行复制实现之后, 官方的 MySQL5.7 版本也提供了类似的功能,由参数 s lave-parallel-type 来控制并行复制策略:
1、配置为 DATABASE ,表示使用 MySQL 5.6 版本的按库并行策略;
2、配置为 LOGICAL_CLOCK ,表示的就是类似 MariaDB 的策略。不过,MySQL 5.7 这个策略,针对并行度做了优化。这个优化的思路也很有趣儿。
在 2018 年 4 月份发布的 MySQL 5.7.22 版本里,MySQL 增加了一个新的并行复制策略,基于 WRITESET 的并行复制。
相应地,新增了一个参数 binlog-transaction-dependency-tracking ,用来控制是否启用这个新策略。这个参数的可选值有以下三种。
1、COMMIT_ORDER,表示的就是前面介绍的,根据同时进入 prepare 和 commit 来判断是否可以并行的策略。
2、WRITESET,表示的是对于事务涉及更新的每一行,计算出这一行的 hash 值,组成集合 writeset。如果两个事务没有操作相同的行,也就是说它们的 writeset 没有交集,就可以并行。
3、WRITESET_SESSION,是在 WRITESET 的基础上多了一个约束,即在主库上同一个线程先后执行的两个事务,在备库执行的时候,要保证相同的先后顺序。
当然为了唯一标识,这个 hash 值是通过“库名 + 表名 + 索引名 + 值”计算出来的。如果一个表上除了有主键索引外,还有其他唯一索引,那么对于每个唯一索引,insert 语句对应的 writeset 就要多增加一个 hash 值。
你可能看出来了,这跟我们前面介绍的基于 MySQL 5.5 版本的按行分发的策略是差不多的。不过,MySQL 官方的这个实现还是有很大的优势:
writeset 是在主库生成后直接写入到 binlog 里面的,这样在备库执行的时候,不需要解析 binlog 内容(event 里的行数据),节省了很多计算量;
不需要把整个事务的 binlog 都扫一遍才能决定分发到哪个 worker,更省内存;
由于备库的分发策略不依赖于 binlog 内容,所以 binlog 是 statement 格式也是可以的。
因此,MySQL 5.7.22 的并行复制策略在通用性上还是有保证的。
当然,对于“表上没主键”和“外键约束”的场景,WRITESET 策略也是没法并行的,也会暂时退化为单线程模型。
图中,虚线箭头表示的是主备关系,也就是 A 和 A’互为主备, 从库 B、C、D 指向的是主库 A。一主多从的设置,一般用于读写分离,主库负责所有的写入和一部分读,其他的读请求则由从库分担。
双击或右键打开MySQL Workbench,进入软件主界面。
点击new connection,会有个弹出框,让我们填写user(用户名),password(密码)。
填写完用户名和密码,点击确定就会出现我们创建的数据库工作空间,例如:local instance MySQL56。
双击local instance MySQL56,进入数据库工作空间。
在左上方找到一个圆柱形带加号的图标,单击该图标,可以显示出数据库名让我们填例如:baidu。
创建好数据库,我们在左菜单栏找到baidu这个数据库,双击该数据库,可以看到下面有个tables,右键table,选择create table,就能创建表了。
在实际的生产中,为了解决Mysql的单点故障,一般都会采用「主备模式」。
MySQL几乎所有的高可用架构,都直接依赖于 binlog。虽然这些高可用架构已经呈现出越来越复杂的趋势,但都是从最基本的一主一备演化过来的。
下图为主备切换流程
在状态 1 中,客户端的读写都直接访问节点 A,而节点 B 是 A 的备库,只是将 A 的更新都同步过来,到本地执行。这样可以保持节点 B 和 A 的数据是相同的。
当需要切换的时候,就切成状态 2。这时候客户端读写访问的都是节点 B,而节点 A 是 B 的备库。
在状态 1 中,虽然节点 B 没有被直接访问,但是依然建议把节点 B(也就是备库)设置成只读(readonly)模式。这样做,有以下几个考虑:
图下图 中画出的就是一个 update 语句在节点 A 执行,然后同步到节点 B 的完整流程图。
备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程,专门用于服务备库 B 的这个长连接。一个事务日志同步的完整过程是这样的:
在备库 B 上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码,以及要从哪个位置开始请求 binlog,这个位置包含文件名和日志偏移量。
在备库 B 上执行 start slave 命令,这时候备库会启动两个线程,就是图中的 io_thread 和 sql_thread。其中 io_thread 负责与主库建立连接。
主库 A 校验完用户名、密码后,开始按照备库 B 传过来的位置,从本地读取 binlog,发给 B。
备库 B 拿到 binlog 后,写到本地文件,称为中转日志(relay log)。
sql_thread 读取中转日志,解析出日志里的命令,并执行。
主库需要复制新增binlog到从库才能完成同步,这个同步过程就是同步延迟。主从延迟最直接的表现是,备库消费中转日志(relay log)的速度,比主库生产 binlog 的速度要慢。
「同步策略」:Master会等待所有的Slave都回应后才会提交,这个主从的同步的性能会严重的影响。
「半同步策略」:Master至少会等待一个Slave回应后提交。
「异步策略」:Master不用等待Slave回应就可以提交。
「延迟策略」:Slave要落后于Master指定的时间。
对于不同的业务需求,有不同的策略方案,但是一般都会采用最终一致性,不会要求强一致性,毕竟强一致性会严重影响性能。
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。
1、首先打开mysql数据库软件进入软件主界面。
2、然后再左侧树里打开自己的的数据库。
3、然后需要点击需要备份的数据库名。
4、如图所示为打开数据库后界面。
5、然后需要点击转储sql文件选项。
6、然后需要打开选择存储文件路径并选择保存。
7、点击保存即可在路径备份好格式为sql的数据库文件。