vlambda博客
学习文章列表

mysql--------一条查询语句是怎么执行的?一条更新语句是怎么执行的?

Mysql数据库是现在应用最为广泛的数据库,几乎大部分公司都会使用Mysql数据库,所以学习Mysql数据库的知识是必不可少的。

一条查询语句是怎么执行?

想了解Sql语句的执行过程,先来了解下mysql的基本架构:

我们可以看到mysql分为server层和存储引擎层,所有的存储引擎都是使用的相同的server层。连接器负责的是和客户端建立连接、获取权限、维持和管理连接。查询缓存是当客户端发起select请求时,首先去缓存中查看是否执行过此语句。需要注意的是查询缓存功能在mysql8.0版本之后就去除掉。分析器的作用是对sql语句进行语法分析。优化器是对sql语句进行优化,生成性能最好的执行计划。执行器部分是拿上优化器生成的执行计划去操作存储引擎,但是在操作引擎之间会判断是否有操作的权限。
一条更新语句是怎么执行?

当执行一条更新语句时,会先把执行语句写到redo log中,然后把要更新的数据写入内存,系统空闲时会把redo log中的记录调用引擎来修改磁盘的数据,redo log只有InnoDB引擎才会有。redo log文件共有4G空间,当空间被写完时就会从文件头开始写。如下图所示:

图中的write pos是当前记录的位置,一边写一边往后移。checkpoint是要擦出的位置,在擦出记录之前要把记录写到磁盘中。

在写完redo log文件之后,就会写bin log日志。bin log是归档日志,其是属于server层,那redo log和bin log有什么不同呢?

  • redo log是InnoDB引擎特有的;bin log是共同拥有的
  • redo log是物理文件;bin log是逻辑文件
  • redo log是循环写入的;bin log是追加写入的方式,不会覆盖掉之前的内容

下图就是一条更新语句的执行过程:

上图的过程便是"两阶段提交"的方案,其中浅色框是在InnoDB引擎中的操作,深色框是在Server层的操作。可以看到在写入redo log中后,事务是处于一个准备提交的状态,只有在写入bin log文件成功之后才会处于commit状态提交事务。

可以通过innodb_flush_log_trx_commit参数的值来保证数据的安全性,当innodb_flush_log_at_trx_commit被 设置为0,日志缓冲每秒一次地被写到redo log日志文件,并且对日志文件做到磁盘操作的刷新,但是在一个事务提交不做任何操作。当这个值为1(默认值)之时,在每个事务提交时,日志缓冲被写到日志文件,对日志文件做到磁盘操作的 刷新。当设置为2之时,在每个提交,日志缓冲被写到文件,但不对日志文件做到磁盘操作的刷新。尽管如此,在对日志文件的刷新在值为2的情况也每秒发生一次。我们必须注意到,因为进程安排问题,每秒一次的 刷新不是100%保证每秒都发生。


也可通过sync_binlog参数来设置bin log文件持久化到磁盘的次数,当设为0时,是让系统决定何时把bin log刷到磁盘;设为1时,每次事务都会刷到磁盘。