美文网首页mysql
mysql一条命令的执行

mysql一条命令的执行

作者: 中2庸 | 来源:发表于2021-12-08 12:20 被阅读0次
    image.png

    1、执行的流程

      从上图大家可以看出,mysql主要涉及两层:server层和存储引擎层,server层主要包括:连接器、缓存、分析器、优化器、执行器,存储引擎是主要涉及数据的存储以及提供接口给server层进行操作,相信上面的图可以给出比较直观的展示

    2、每个环节的作用

    客户端:主要适配不同开发语言,通过客户端连接上数据库server;

    连接器:客户端和连接器对接,连接器会对客户端发起的连接进行鉴权,如果网络是连通的,对于有效的用户连接则会建议连接;同时对于连接存在长连接、短连接的情况,具体使用看场景而定;
    短连接:连接-> 通信-> 关闭连接,适用于操作不频繁的通信场景下,但是对于高并发的情况下,例如每秒上万的请求,那么使用短连接是合适,因为采用长连接的话,占用的系统资源会更多;同时这里提到一个扩展点,对于高并发的情况下,可以通过调整服务器的端口范围和减少端口回收延期时间,另外还有一种方式就是一个主机多个ip来扩展;
    长连接:是一些驱动、驱动框架、ORM工具的特性,适用于频繁与服务器通信发送数据,减少了数据库scoket连接开销,但是长连接过多、并且不释放,会导致内存占用提升,它可以节省创建连接的开销,但维持连接也是需要内存的;
    连接池:是应用服务器的组件,它可以通过参数来配置连接数、连接检测、连接的生命周期,连接池或长连接使用的连接数很多,有可能会超过数据库实例的限制,那么就需要留意连接相关的设置了,比如连接池的最小、最大连接数设置

    缓存:对于缓存,开启缓存后mysql server会先查询缓存,缓存的存储在内存,使用key-value模式进行存储,key是sql语句,value是对应的值,但是在mysql 8.0之后,缓存已经被删除了;缓存全面讲解可参考:https://zhuanlan.zhihu.com/p/55947158

    分析器:简单理解为sql语句进来之后,会进行sql语句的词法分析、语法分析、以及涉及哪些表哪些列,同时检查这些表和列是否存在,不存在则抛出异常;

    优化器:对于一条sql在执行之前,进行判定是否可以优化执行方式,例如是否走索引,化器是在表里面有多个索引的时候,决定使用哪个索引,以及在存在多种执行路径的情况下,选择哪种执行方式,如join操作;

    执行器:对真实的sql进行执行,开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,操作后数据存在内存,然后写入redo_log,此时redo_log进入prepare状态,然后写入bin_log,然后调用存储引擎接口提交redo_log commit,进行数据处理和记录,这里在server层会记录bin_log日志,在存储引擎会执行redo_log日志,这里可以想下为啥需要记录这两个日志,目的是为了啥?

    3、两种日志的说明

      首先说下redo_log,他是属于物理日志,记录数据库操作的真实数据存储页的变化,首先在执行完数据操作后,存储引擎会将更新数据更新在内存,然后进入prepare状态,之后server层会记录逻辑日志bin_log,记录好bin_log后,redo_log提交commit,事务完成,可以看出来redo_log进行了两步操作,也就是所谓的两阶段提交,这个时候回到我们前面的提问,为啥需要这么做?这个时候你的脑海里是不是,冒出一下几个问题:

    这两种日志的作用是啥?

    bin_log作用:

    1,用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
    2,用于数据库的基于时间点的还原。
    binlog 有三种模式:Statement(基于 SQL 语句的复制)、Row(基于行的复制) 以及 Mixed(混合模式)

    redo_log作用

    确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启 mysql 服务的时候,根据 redo log 进行重做,从而达到事务的持久性这一特性。InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。

    两种日志的区别:

    • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
    • redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
    • redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志

    只记录一种日志行不行?

    • 为什么要分两步?目的是为了啥,不这么做有什么后果?
      首先我们看下第一个问题:
      这两种日志的作用是啥?
      我们一起看下第2个问题:
    • 只记录一种日志行不行?只记录一种日志,首先innodb是存储引擎层记录的,bin_log是server层记录的,如果仅记录其中一种,当写入bin_log后crash,这样bin_log没法和存储层保持一致;因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力

    为什么要分两步?目的是为了啥,不这么做有什么后果?

    目的:为了让两份日志之间的逻辑一致
    事务的提交要先写redo log(prepare),再写binlog,最后再提交(commit)。这里为什么要有个prepare的动作?redo log直接commit状态不行吗?假设redo log直接提交,在写binlog的时候,发生了crash,这时binlog就没有对应的数据,那么所有依靠binlog来恢复数据的slave,就没有对应的数据,导致主从不一致。所以需要通过两段式(2pc)提交来保证redo log和binlog的一致性是非常有必要的。具体的步骤是:处于prepare状态的redo log,会记录2PC的XID,binlog写入后也会记录2PC的XID,同时会在redo log上打上commit标识

    总结

      redolog和binlog具有关联行,在恢复数据时,redolog用于恢复主机故障时的未更新的物理数据,binlog用于备份操作。每个阶段的log操作都是记录在磁盘的,在恢复数据时,redolog 状态为commit则说明binlog也成功,直接恢复数据;如果redolog是prepare,则需要查询对应的binlog事务是否成功,决定是回滚还是执行。

    4、参考文献

    https://time.geekbang.org/column/article/68633
    https://zhuanlan.zhihu.com/p/55947158
    https://blog.csdn.net/tototuzuoquan/article/details/78573955
    https://juejin.cn/post/7007945074080235534

    相关文章

      网友评论

        本文标题:mysql一条命令的执行

        本文链接:https://www.haomeiwen.com/subject/gzttfrtx.html