Mysql角色与日志初体验(从查询更新入手)

前提:
当我们认知一个人的时候,首先要观察这个人的外在,再去深入了解这个人的内涵。对于我们认识学习mysql也是如此,要先明白它的各个角色组成(形象的比喻)。

Mysql三大角色

客户端:

客户端主要用来发起对mysql请求 ,比如我们输入查询语句,连接mysql server(mysql -uroot -proot)等。

服务端(核心功能):

连接器

定义:主要是用来处理客户端和服务端之间的连接,权限判断。可以通过show processlist指令来查看连接的状态,连接会有一个默认的超时时间,这个时间可以由wait_timeout控制。
分类:
长连接(长时间使用同一个连接,只有客户端持有请求,优点是稳定,因为建立连接的过程比较复杂,尽量使用。缺点是容易占用大量内存。)
解决上述的问题方法主要有两个:

  1. 定期断开长连接。
  2. 新版本的mysql可以使用mysql_reset_connection来重新初始化连接资源)

查询缓存

缓存中以key-value形式来存储数据,key是sql语句,value是查询返回的值,不推荐使用,每次mysql更新表的时候,都会把所有缓存数据清除。高版本的mysql已经删除去掉缓存

分析器

对mysql语句进行词法语法分析,先把你输入的语句进行词法分析,说白了就是拆分各个字段,并识别其中的字段,比如id啥的。完成词法分析后,就要对输入的mysql语句进行语法分析。

优化器

优化器的作用主要就是提高查询的效率,当表里面有多个索引的时候,优先决定使用那个索引,或者在有关键词join存在的时候,决定表的连接顺序

执行器

分析器让你知道做什么,优化器让你知道如何做更快,经过这两步就可以真正来执行语句了。执行之前需要再次判断你是不是对这张表有权限,包括查询缓存的时候也是如此,也要再做一次权限判断。权限判定Ok的话,就会根据表的引擎定义,来调用相应存储引擎的接口查询数据

存储引擎

现有的存储引擎包括:InnoDB(默认)、MyISAM 、Memory,可以通过engine = Memory来指定存储引擎

=======================================================================

Mysql的查询流程

知道了MySQL的角色组成后,接下来我们来看看mysql的查询流程

  1. 客户端向mysql server发起连接请求,经过连接器校验成功后,就可以向mysql server发送sql请求
  2. 请求首先会查询缓存,如果缓存中没有,则经过分析器、优化器、执行器,最后调用到存储引擎的接口来查询数据并返回

redo log和binlog

Mysql的更新流程更新流程和查询流程类似,不一样的点在于,更新涉及到两个重要的日志模块:redo log(重做日志)和binlog(归档日志)

  1. redo log(InnoDB日志,记录这个页做了什么改动) 如果mysql每次都把数据直接写入磁盘,查询也是直接查询磁盘,这样想想IO效率都很低,所以mysql引进了WAL(Write-Ahead Logging)技术,这个技术说白了就是没有直接把数据写进磁盘,而是先把数据写到日志中,等悠闲的时候再把日志中的数据写入到磁盘中。机制是这样的,如果今天操作不多,InnoDB引擎就会选择在空闲的时间将日志的数据更新到磁盘中。但是操作特别多的话,日志已经满了的话,就会把一部分数据先更新到磁盘中了解了redo log的作用后,我们再来看redo log的构造。在InnoDB中redo log是固定大小的。其构造就像一个环。其中有两个重要的类似指针的东西,一个是write pos(记录当前写的位置),另外一个是check point(表示要擦除的位置),之两个会沿着相同的方向旋转,其中write pos和checkpoint之间空着的位置就是日志中空闲的位置,write pos追上check point这个时候说明日志已经写完了,就需要更新数据到磁盘中。redo log可以防止mysql出现异常的时候,不会丢失记录,这种能力成为crash-safe
  2. binlog(server 层日志,两种模式:1、statement模式:记录sql语句 2、row格式:记录行的内容)这个日志是以前在mysql的存引擎还是MysISAM的时候用的,这个日志并没有crash-safe的能力,它只能由来归档

binlog日志 和 redlog日志的差别

  1. redo log是InnoDB引擎特有的,binlog是mysql server层的,所有引擎都可以使用
  2. redo log是物理日志,记录某个数据页做了什么修改,binlog是逻辑日志,记录这个语句的原始逻辑
  3. redo log是循环写,空间固定会用完;binlog是可以追加写入的,追加写的是binlog写到一定大小后会切换到下一个,不会覆盖以前的日志

更新语句的执行流程

  1. 执行器先根据id找到对应的行,如果这一行在内存中,就在内存中查找,否则需要从磁盘读入内存,再返回。
  2. 执行器拿到数据后,把值修改,再调用引擎接口写入数据。
  3. 引擎将这行数据更新到内存中,同时将更新记录到redo log,此时的redo log处于prepare状态,然后告知执行器执行完毕,可以提交事务。
  4. 执行器生成这个操作的binlog,并把binlog写入磁盘。
  5. 执行器调用引擎提交事务的接口,引擎把刚刚写入的redo log改成commit状态,更新完成。

ps

这里把redo log的写入拆分成两个步骤(一个是prepare,另外一个是commit)这里是一个两阶段提交,为了让两份日志之间的逻辑一致。
一般恢复数据到哪个时候的一个状态都是用binlog来实现的,这里两阶段提交就是为了binlog的日志和redol log的日志一样,恢复数据的时候不会出现问题。
redo log用于保证crash-safe能力,innodb_flush_log_At_trx_commit 这个参数设置为1,表示每次事务的redo log都直接持久化到磁盘 。sync_binlog参数设置为1的时候,表示每次事务的binlog都持久化到磁盘。

未完待续。。。。。。。。

猜你喜欢

转载自blog.csdn.net/weixin_42683077/article/details/106948931