《Mysql - Mysql 是如何保证主备一致的?》

一:Mysql 主备的基本原理?

  - 主备切换流程(M-S 架构

    - 

  - 在状态 1 中,客户端的读写都直接访问节点 A,而节点 B 是 A 的备库,只是将 A 的更新都同步过来,到本地执行。

  - 这样可以保持节点 B 和 A 的数据是相同的。

  - 当需要切换的时候,就切成状态 2。这时候客户端读写访问的都是节点 B,而节点 A 是 B 的备库。

  - 在状态 1 中,虽然节点 B 没有被直接访问,但是依然建议你把节点 B(也就是备库)设置成只读(readonly)模式。

    - 有时候一些运营类的查询语句会被放到备库上去查,设置为只读可以防止误操作;

    - 防止切换逻辑有 bug,比如切换过程中出现双写,造成主备不一致;

    - 可以用 readonly 状态,来判断节点的角色。 

  - 备库 readonly 不会影响同步更新,因为 readonly 设置对超级 (super) 权限用户是无效的,而用于同步更新的线程,就拥有超级权限。 

 

二:两个 Mysql 实例是如何通信的?

  - 通信流程图

    - 

    - 主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写 binlog。

 

  - 详解流程

    - 备库 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 的三种格式

  - 概念

    - binlog 共有三种格式 statement\row\还有一种 mixed,其实它就是前两种格式的混合。

 

  -  statement

    - 原理

      - 当 binlog_format=statement 时,binlog 里面记录的就是 SQL 语句的原文

 

    - 问题

      - 由于 statement 格式下,记录到 binlog 里的是语句原文,因此可能会出现这样一种情况:在主库执行这条 SQL 和 备库执行的 SQL 不一致。

      - 因此,MySQL 认为这样写是有风险的。 

 

  - row

    - 原理

      - 因为有些 statement 格式的 binlog 可能会导致主备不一致,所以要使用 row 格式。

      - 当 binlog_format 使用 row 格式的时候,binlog 里面记录了真实操作行的主键 id。

      - 这样 binlog 传到备库去的时候,就肯定会操作 主键 的行,不会有主备操作不同行的问题。 

 

    - 问题

      - 很占空间。

        - 比如你用一个 delete 语句删掉 10 万行数据,用 statement 的话就是一个 SQL 语句被记录到 binlog 中,占用几十个字节的空间。

        - 但如果用 row 格式的 binlog,就要把这 10 万条记录都写到 binlog 中。

        - 这样做,不仅会占用更大的空间,同时写 binlog 也要耗费 IO 资源,影响执行速度。 

 

    - 现在越来越多的场景要求把 MySQL 的 binlog 格式设置成 row。因为 row 有一个很特别的好处:恢复数据。

 

  -  mixed

    - 由于 row 太占空间,而 statement 是不安全的, 所以,MySQL 就取了个折中方案,也就是有了 mixed 格式的 binlog。

    - mixed 格式的意思是,MySQL 自己会判断这条 SQL 语句是否可能引起主备不一致,如果有可能,就用 row 格式,否则就用 statement 格式。

    - 也就是说,mixed 格式可以利用 statment 格式的优点,同时又避免了数据不一致的风险。 

 

四:M - M 架构(循环复制问题)

  - M-M 架构图(互为主备)

    - 

    -  双 M 结构和 M-S 结构,其实区别只是多了一条线

      - 即:节点 A 和 B 之间总是互为主备关系。

      - 这样在切换的时候就不用再修改主备关系。

 

  - 如果节点 A 同时是节点 B 的备库,相当于又把节点 B 新生成的 binlog 拿过来执行了一次,然后节点 A 和 B 间,会不断地循环执行这个更新语句,也就是循环复制了。这个要怎么解决呢?

 

  - 解决办法

    - 规定两个库的 server id 必须不同,如果相同,则它们之间不能设定为主备关系;

    - 一个备库接到 binlog 并在重放的过程中,生成与原 binlog 的 server id 相同的新的 binlog;

    - 每个库在收到从自己的主库发过来的日志后,先判断 server id,如果跟自己的相同,表示这个日志是自己生成的,就直接丢弃这个日志。 

 

posted @ 2019-06-18 15:59  Zzz哈  Views(474)  Comments(0Edit  收藏  举报