MySQL实战45讲
林晓斌
网名丁奇,前阿里资深技术专家
立即订阅
42945 人已学习
课程目录
已完结 48 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 这一次,让我们一起来搞懂MySQL
免费
基础篇 (8讲)
01 | 基础架构:一条SQL查询语句是如何执行的?
02 | 日志系统:一条SQL更新语句是如何执行的?
03 | 事务隔离:为什么你改了我还看不见?
04 | 深入浅出索引(上)
05 | 深入浅出索引(下)
06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
07 | 行锁功过:怎么减少行锁对性能的影响?
08 | 事务到底是隔离的还是不隔离的?
实践篇 (37讲)
09 | 普通索引和唯一索引,应该怎么选择?
10 | MySQL为什么有时候会选错索引?
11 | 怎么给字符串字段加索引?
12 | 为什么我的MySQL会“抖”一下?
13 | 为什么表数据删掉一半,表文件大小不变?
14 | count(*)这么慢,我该怎么办?
15 | 答疑文章(一):日志和索引相关问题
16 | “order by”是怎么工作的?
17 | 如何正确地显示随机消息?
18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?
19 | 为什么我只查一行的语句,也执行这么慢?
20 | 幻读是什么,幻读有什么问题?
21 | 为什么我只改一行的语句,锁这么多?
22 | MySQL有哪些“饮鸩止渴”提高性能的方法?
23 | MySQL是怎么保证数据不丢的?
24 | MySQL是怎么保证主备一致的?
25 | MySQL是怎么保证高可用的?
26 | 备库为什么会延迟好几个小时?
27 | 主库出问题了,从库怎么办?
28 | 读写分离有哪些坑?
29 | 如何判断一个数据库是不是出问题了?
30 | 答疑文章(二):用动态的观点看加锁
31 | 误删数据后除了跑路,还能怎么办?
32 | 为什么还有kill不掉的语句?
33 | 我查这么多数据,会不会把数据库内存打爆?
34 | 到底可不可以使用join?
35 | join语句怎么优化?
36 | 为什么临时表可以重名?
37 | 什么时候会使用内部临时表?
38 | 都说InnoDB好,那还要不要使用Memory引擎?
39 | 自增主键为什么不是连续的?
40 | insert语句的锁为什么这么多?
41 | 怎么最快地复制一张表?
42 | grant之后要跟着flush privileges吗?
43 | 要不要使用分区表?
44 | 答疑文章(三):说一说这些好问题
45 | 自增id用完怎么办?
特别放送 (1讲)
直播回顾 | 林晓斌:我的 MySQL 心路历程
结束语 (1讲)
结束语 | 点线网面,一起构建MySQL知识网络
MySQL实战45讲
登录|注册

27 | 主库出问题了,从库怎么办?

林晓斌 2019-01-14
在前面的第242526篇文章中,我和你介绍了 MySQL 主备复制的基础结构,但这些都是一主一备的结构。
大多数的互联网应用场景都是读多写少,因此你负责的业务,在发展过程中很可能先会遇到读性能的问题。而在数据库层解决读性能问题,就要涉及到接下来两篇文章要讨论的架构:一主多从。
今天这篇文章,我们就先聊聊一主多从的切换正确性。然后,我们在下一篇文章中再聊聊解决一主多从的查询逻辑正确性的方法。
如图 1 所示,就是一个基本的一主多从结构。
图 1 一主多从基本结构
图中,虚线箭头表示的是主备关系,也就是 A 和 A’互为主备, 从库 B、C、D 指向的是主库 A。一主多从的设置,一般用于读写分离,主库负责所有的写入和一部分读,其他的读请求则由从库分担。
今天我们要讨论的就是,在一主多从架构下,主库故障后的主备切换问题。
如图 2 所示,就是主库发生故障,主备切换后的结果。
图 2 一主多从基本结构 -- 主备切换
相比于一主一备的切换流程,一主多从结构在切换完成后,A’会成为新的主库,从库 B、C、D 也要改接到 A’。正是由于多了从库 B、C、D 重新指向的这个过程,所以主备切换的复杂性也相应增加了。
接下来,我们再一起看看一个切换系统会怎么完成一主多从的主备切换过程。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《MySQL实战45讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(37)

  • 某、人 置顶
    1.如果业务允许主从不一致的情况那么可以在主上先show global variables like 'gtid_purged';然后在从上执行set global gtid_purged =' '.指定从库从哪个gtid开始同步,binlog缺失那一部分,数据在从库上会丢失,就会造成主从不一致
    2.需要主从数据一致的话,最好还是通过重新搭建从库来做。
    3.如果有其它的从库保留有全量的binlog的话,可以把从库指定为保留了全量binlog的从库为主库(级联复制)
    4.如果binlog有备份的情况,可以先在从库上应用缺失的binlog,然后在start slave

    作者回复: 非常好👍

    2019-01-15
    19
  • Mr.Strive.Z.H.L 置顶
    老师您好:
    在实际工作中,主从备份似乎是mysql用的最多的高可用方案。
    但是个人认为主从备份这个方案的问题实在太多了:
    1. binlog数据传输前,主库宕机,导致提交了的事务数据丢失。
    2. 一主多从,即使采用半同步,也只能保证binlog至少在两台机器上,没有一个机制能够选出拥有最完整binlog的从库作为新的主库。
    3. 主从切换涉及到 人为操作,而不是全自动化的。即使在使用GTID的情况下,也会有binlog被删除,需要重新做从库的情况。
    4. 互为主备,如果互为主备的两个实例全部宕机,mysql直接不可用。

    mysql应该有更强大更完备的高可用方案(类似于zab协议或者raft协议这种),而在实际环境下,为什么主从备份用得最多呢?

    作者回复: 3 这个应该是可以做到自动化的。
    4 这个概率比较小,其实即使是别的三节点的方案,也架不住挂两个实例,所以这个不是MySQL主备的锅。

    前面两点提得很对哈。
    其实MySQL到现在,还是提供了很多方案可选的。很多是业务权衡的结果。

    比如说,异步复制,在主库异常掉电的时候可能会丢数据。
    这个大家知道以后,有一些就改成semi-sync了,但是还是有一些就留着异步复制的模式,因为semi-sync有性能影响(一开始35%,现在好点15%左右,看具体环境),而可能这些业务认为丢一两行,可以从应用层日志去补。 就保留了异步复制模式。

    最后,为什么主从备份用得最多,我觉得有历史原因。多年前MySQL刚要开始火的时候,大家发现这个主备模式好方便,就都用了。
    而基于其他协议的方案,都是后来出现的,并且还是陆陆续续出点bug。
    涉及到线上服务,大家使用新方案的热情总是局限在测试环境的多。

    semi-sync也是近几年才开始稳定并被一些公司开始作为默认配置。

    新技术的推广,在数据库上,确实比其他领域更需要谨慎些,也算是业务决定的吧^_^
    好问题👍
    以上仅一家之言哈😆

    2019-01-18
    11
  • 悟空 置顶
    看过上篇后想到一个问题:
    级联复制A->B->C结构下, 从库C的Seconds_Behind_Master的时间计算问题.
    假定当前主库A仅有一个DDL要进行变更,耗时1分钟.那么从库C的SBM值最大应该是多少时间?
    是1分钟, 2分钟, 还是3分钟呢 ?
    带着疑问看了一下测试从库C的binlog文件中的时间戳,得出结论应该是3分钟.

    打破之前认知 🤦‍♀️ . 请老师解惑 , 谢谢 !

    作者回复: 是的,因为算的是:当前执行时间,跟*日志时间*的差距

    而这个日志时间,是在A上执行出来的。

    好问题,很好的验证过程。

    2019-01-14
    1
    9
  • 张永志
    今天问题回答:
    GTID主从同步设置时,主库A发现需同步的GTID日志有删掉的,那么A就会报错。
    解决办法:
    从库B在启动同步前需要设置 gtid_purged,指定GTID同步的起点,使用备份搭建从库时需要这样设置。

    如果在从库上执行了单独的操作,导致主库上缺少GTID,那么可以在主库上模拟一个与从库B上GTID一样的空事务,这样主从同步就不会报错了。

    作者回复: 你已经理解GTID的机制啦👍

    2019-01-14
    7
  • Lukia
    对于老师之前对其他他同学的回答还有一点疑问需要请教一下:

    Master A上的binlog时间不是在事物commit之前写binlog的时间吗,那么在从节点C上的SBM最大值不应该是2分钟吗?(按3分钟的答案来说,Master A上执行的1分钟为啥要算进去呢?)

    看过上篇后想到一个问题:
    级联复制A->B->C结构下, 从库C的Seconds_Behind_Master的时间计算问题.
    假定当前主库A仅有一个DDL要进行变更,耗时1分钟.那么从库C的SBM值最大应该是多少时间?
    是1分钟, 2分钟, 还是3分钟呢 ?
    带着疑问看了一下测试从库C的binlog文件中的时间戳,得出结论应该是3分钟.

    打破之前认知 🤦‍♀️ . 请老师解惑 , 谢谢 !
    作者回复: 是的,因为算的是:当前执行时间,跟*日志时间*的差距

    而这个日志时间,是在A上执行出来的。

    好问题,很好的验证过程。


    作者回复: 嗯,多一跳确实是应该多1分钟,在c的最长延迟时间应该是2分钟

    2019-02-18
    4
  • 时隐时现
    其实基于gtid复制有个大坑,在主库上千万不要执行reset master,否则从库不会报错,只会跳过gno < current_no的事务,造成一个现象就是主库复制没有中断,但是主库上的数据无法同步到从库。

    作者回复: 是的,
    不过reset master这种语句。。就算是基于position的协议,谁在线上主库上执行,也是直接当做删数据论处的了😅

    2019-01-31
    4
  • _CountingStars
    老师我有一个问题 如果数据库已经有完成了很多事务 实例 A’的 GTID集合和 实例 B的 GTID集合 是不是很大,这个GTID是从binglog里一点一点的解析出来所有的事务的吗?这样是不是会很慢 ?在所有binlog里定位某个GTID是不是效率也很低

    作者回复: 好问题,👍
    在binlog文件开头,有一个Previous_gtids, 用于记录 “生成这个binlog的时候,实例的Executed_gtid_set”, 所以启动的时候只需要解析最后一个文件;

    同样的,由于有这个Previous_gtids,可以快速地定位GTID在哪个文件里。

    2019-01-15
    3
  • 春困秋乏夏打盹
    回答undifined的第二个问题
    A-A'-B这样的级联结构
    A (binlog:A:1-M)
    A'(binlog: A:1-M,B:1-N) ,A'上面的操作记为B:1-N
    B (binlog: A:1-M,B:1-N,C:1-X) B上面的操作记为C:1-X
    ---A,B,C分别为A-A'-B的uuid

    作者回复: 对的
    总之就是,一个主备关系里,备库的GTID集合应该包含主库的GTID集合。

    2019-01-16
    2
  • fuyu
    seta 和 setb 里的集合大小不会很大?

    作者回复: 大没关系呀,是分段的,比如 server_uuid_of_a:1-1000000,就一个段

    2019-01-15
    2
  • 老师您好,假如a宕机了,需要把从切换到a',这时候业务已经有感知了吧?怎么能让业务尽量没有感知呢?谢谢老师

    作者回复: 这种情况下,不可能业务完全无感知,

    但是如果业务代码有“重连并重试”的逻辑,并且切换足够快,就可以对业务无影响,前提是要解决主备延迟问题,就是25、26两篇提到的

    2019-01-14
    2
  • 灵犀andy
    林老师,我是看了很久了您的专栏的一位粉丝,最近我们计划在docker中跑mysql,但是我觉的docker中运维mysql太麻烦了,xtrabackup工具好像在docker中就无法安装。还有主从,MHA等,请问docker中适合跑mysql吗,优点和缺点是什么?

    作者回复: docker中跑MySQL没问题的~

    2019-06-19
    1
  • Mr.Strive.Z.H.L
    老师您好:
    之前讲过 互为主备 的场景下,会出现循环复制的问题,今天这节讲了GTID。
    如果使用GTID,那么 循环复制 的问题自然而然就解决了呀??!!

    作者回复: 哈哈,you got it

    2019-01-18
    1
  • PengfeiWang
    老师,您好: 文中对于sql_slave_skip_counter=1的理解似乎有偏差,官方文档中的解释是:
    When you use SET GLOBAL sql_slave_skip_counter to skip events and the result is in the middle of a group, the slave continues to skip events until it reaches the end of the group. Execution then starts with the next event group.
    按照官方文档的解释,命令sql_slave_skip_counter=1 应该是跳过一个事务中的1个event,除非这个事务是有单个event组成的,才会跳过一个事务。
     

    作者回复: 你这个是好问题,

    确实只是跳过一个event,不过文档中说了呀
    “the slave continues to skip events until it reaches the end of the group. ”,
    所以效果上等效于跳过一个事务哦

    2019-01-14
    1
  • PengfeiWang
    老师,你好:在生产环境(基于位点的主备切换)中,经常会遇到这样的场景:备库由于硬件或其他原因异常宕机,恢复后重启备库,执行start slave命令,总会遇到1062主键重复的报错,一直解释不清楚为什么?

    作者回复: 看一下这个语句的结果, 会受这几个参数的影响哈
    select * from information_schema.GLOBAL_VARIABLES where VARIABLE_NAME in ('master_info_repository','relay_log_info_repository','sync_master_info','sync_relay_log_info', 'sync_binlog', 'innodb_flush_log_at_trx_commit');

    2019-01-14
    1
  • undifined
    老师 有几个问题:
    1. 会不会出现主库切换后,B 中已经执行过的事务,而 A'由于网络延迟还没有收到,此时已经对 B 执行切换主库,这时候,B 中有该 GTID,但是 A'中没有,这种情况会怎么处理
    2. 如果 A 是主库,A' 备库,B 是 A'的从库,此时 B 的 GTID 集合应该是 server_uuid_of_A':1-N,此时 A'宕机,B 改为监听 A,这时候A 和 B 的 GTID 集合没有交集,会不会发生 A 将所有的binlog 重新发给B
    3. 思考题我的理解是从主库中 dump 出相关的数据,在备库中执行后再次执行 start slave;评论中说到从其他从库获取,但是如果只有一主一从,有 binlog 丢失,是不是只要 dump 文件恢复这一个办法

    作者回复: 1. 这个也是异步复制导致的,只有semi-sync能解了。。
    2. 不是哦,如果“ A 是主库,A' 备库,B 是 A'的从库”,那所有A的更新也都会通过A'传给B,所以B的GTID集合正常就是包含了A和A'的
    3. “如果只有一主一从,有 binlog 丢失”,是的,就只有备库重做了

    2019-01-14
    1
  • 大坤
    今天问题回答,由于GTID具有全局唯一性,那么其它正常的gtid已经被复制到了其他从库上了,只需要切换gtid到其他从库,等待同步完毕后在切换回主库即可

    作者回复: 这个想法很不错 👍

    2019-01-14
    1
  • 往事随风,顺其自然
    执行事务之前生成GTID,系统怎么知道下次要生成事物,是预生成留在那?

    作者回复: 提交事务的时候才生成GTID

    2019-01-14
    1
  • 左瞳
    主库执行更新语句是写入缓存和redolog,并没有同步到binlog,这样从库的延迟不是会很高?
    2019-08-23
  • Eagles
    老师你好,请问机器启动以后,有什么情况会导致uuid变化吗?比如更改cnf文件里的serverId
    2019-08-13
  • godtrue
    server_uuid 是一个实例第一次启动时自动生成的,是一个全局唯一的值?
    在集群环境下这个怎么保证全局唯一的
    2019-08-04
收起评论
37
返回
顶部