前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mysql索引和日志相关问题

mysql索引和日志相关问题

原创
作者头像
历久尝新
修改2020-06-05 17:55:22
7660
修改2020-06-05 17:55:22
举报
文章被收录于专栏:学而时习之

日志相关问题:

1. 在两阶段提交的不同瞬间, mysql如果发生异常重启, 怎么保证数据的完整性?

两阶段示意图

2. 上图中commit步骤与事务的commit语句有什么区别?

  • 事务的commit是mysql的语法, 用于提交一个事务,begin/start transaction 配对使用;
  • 图中的commit是指事务提交过程中国年的一个小步骤, 也是最后一步。当这个步骤执行完成后,这个事务就提交完成了
  • “commit 语句”执行的时候,会包含“commit 步骤

3. 两阶段不同时刻,mysql异常重启会出现什么现象?

  • 如果在图中时刻A(写redolog prepare之后, binlog之前, 发生了crash)崩溃. 此时binlog还没写, redolog没提交, 所以崩溃恢复的时候这个事务会回滚, 此时binlog还没写, 所以也不会传到备库中.
  • 如果在时刻B发生了crash(binlog写完, redolog未提交前)
    • 如果redolog 中的事务是完整的, 已经有了commit标识(zhì), 则直接提交;
    • 如果redolog 中的事务只有prepare, 则判断对应事务的binlog是否完整:
      • 如果是, 则提交事务;
      • 否则回滚事务

4. 如何知道binlog是否是完整的?

一个事务的binlog是有完整的格式的:

  • statement格式的binlog, 最后会有一个commit
  • row格式的binlog, 最后会有一个xid event

5. redolog 和 binlog是如何关联起来的?

他们有一个共同的字段, 叫做xid, 崩溃恢复的时候, 会按照顺序扫描redolog:

  • 如果碰到既有prepare又有commit的redolog, 则直接提交;
  • 如果碰到只有prepare而没有commit的redolog, 就拿着xid去binlog 找对应的事务;

6. 处于prepare阶段的redolog 加上完整的binlog, 重启就能恢复, mysql为什么要这么设计?

在时刻B中, binlog写完之后, mysql崩溃, 这时候由于binlog已经写入, 之后就会被从库(或者用这个binlog恢复出来的库)使用,所以主库再恢复的时候, 也要提交这个事务, 这样保证了主库和备份库的数据一致性.

7. 追问6, 如过这样,为什么需要两阶段提交呢? 为什么不写完redolog 在写binlog, 崩溃恢复的时候, 必须两个日志都完整才可以, 这不是一样的逻辑吗?

两阶段提交是典型的分布式系统的问题, 并不是mysql独有的

举个栗子.

对于innodb引擎来说 如果redolog 提交完成了, 事务就不能回滚了, 而如果redolog直接提交, 然后写入binlog 失败, innodb又回滚不了, 数据和binlog日志就不一致了.

两阶段提交就是为了给所有人一个机会,当每个人都说“我 ok”的时候,再一起提交。

8. 不引入两个日志,也就没有两阶段提交的必要了。只用 binlog 来支持崩溃恢复,又能支持归档,不就可以了?

问题大意是, 只保留binlog, 将提交流程改成: "数据更新到内存" --> "写binlog" --> "提交事务" 是不是也具有了crash-safe能力.

只用 binlog 支持崩溃恢复
只用 binlog 支持崩溃恢复

答案是不可以:

  • 历史原因: innodb并不是mysql 的原生的存储引擎, mysql的原生引擎是myisam, 设计之初就没有支持crash-safe能力.
  • 实现原因: binlog没有能力恢复数据页, 如果在上图中标的位置, 也就是binlog2写完, 但是整个事务还没有commit的时候, mysql发生了crash, 重启后,引擎内部事务 2 会回滚,然后应用 binlog2 可以补回来;但是对于事务 1 来说,系统已经认为提交完成了,不会再应用一次 binlog1。但是,InnoDB 引擎使用的是 WAL 技术,执行事务的时候,写完内存和日志,事务就算完成了。如果之后崩溃,要依赖于日志来恢复数据页。也就是说在图中这个位置发生崩溃的话,事务 1 也是可能丢失了的,而且是数据页级的丢失。此时,binlog 里面并没有记录数据页的更新细节,是补不回来的。

9. 那能不能反过来,只用 redo log,不要 binlog?回答:如果只从崩溃恢复的角度来讲是可以的。你可以把 binlog 关掉

如果只从崩溃恢复的角度来讲是可以的。你可以把 binlog 关掉,这样就没有两阶段提交了,但系统依然是 crash-safe 的。

10. redo log 一般设置多大?

redo log 太小的话,会导致很快就被写满,然后不得不强行刷 redo log,这样 WAL 机制的能力就发挥不出来了。所以,如果是现在常见的几个 TB 的磁盘的话,就不要太小气了,直接将 redo log 设置为 4 个文件、每个文件 1GB 吧。

11. 正常运行中的实例,数据写入后的最终落盘,是从 redo log 更新过来的还是从 buffer pool 更新过来的呢?

实际上,redo log 并没有记录数据页的完整数据,所以它并没有能力自己去更新磁盘数据页,也就不存在“数据最终落盘,是由 redo log 更新过去”的情况。

  • 如果是正常运行的实例的话,数据页被修改以后,跟磁盘的数据页不一致,称为脏页。最终数据落盘,就是把内存中的数据页写盘。这个过程,甚至与 redo log 毫无关系
  • 在崩溃恢复场景中,InnoDB 如果判断到一个数据页可能在崩溃恢复的时候丢失了更新,就会将它读到内存,然后让 redo log 更新内存内容。更新完成后,内存页变成脏页,就回到了第一种情况的状态。

12. redo log buffer 是什么?是先修改内存,还是先写 redo log 文件?

在一个事务的更新过程中,日志是要写多次的。比如下面这个事务:

代码语言:sql
复制
begin;
insert into t1 ...
insert into t2 ...
commit;

这个事务要往两个表中插入记录,插入数据的过程中,生成的日志都得先保存起来,但又不能在还没 commit 的时候就直接写到 redo log 文件里。

所以,redo log buffer 就是一块内存,用来先存 redo 日志的。也就是说,在执行第一个 insert 的时候,数据的内存被修改了,redo log buffer 也写入了日志。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 日志相关问题:
    • 1. 在两阶段提交的不同瞬间, mysql如果发生异常重启, 怎么保证数据的完整性?
      • 两阶段示意图
    • 2. 上图中commit步骤与事务的commit语句有什么区别?
      • 3. 两阶段不同时刻,mysql异常重启会出现什么现象?
        • 4. 如何知道binlog是否是完整的?
          • 5. redolog 和 binlog是如何关联起来的?
            • 6. 处于prepare阶段的redolog 加上完整的binlog, 重启就能恢复, mysql为什么要这么设计?
              • 7. 追问6, 如过这样,为什么需要两阶段提交呢? 为什么不写完redolog 在写binlog, 崩溃恢复的时候, 必须两个日志都完整才可以, 这不是一样的逻辑吗?
                • 8. 不引入两个日志,也就没有两阶段提交的必要了。只用 binlog 来支持崩溃恢复,又能支持归档,不就可以了?
                  • 9. 那能不能反过来,只用 redo log,不要 binlog?回答:如果只从崩溃恢复的角度来讲是可以的。你可以把 binlog 关掉
                    • 10. redo log 一般设置多大?
                      • 11. 正常运行中的实例,数据写入后的最终落盘,是从 redo log 更新过来的还是从 buffer pool 更新过来的呢?
                        • 12. redo log buffer 是什么?是先修改内存,还是先写 redo log 文件?
                        相关产品与服务
                        云数据库 SQL Server
                        腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档