zoukankan      html  css  js  c++  java
  • 一条更新语句在MySQL上是如何执行的

    本篇文章主要是以一条SQL查询语句和一条SQL更新语句是如何执行的带出来整体的MySQL架构

    下方的图片是整体一个情况的概括,像查询缓存在MySQL8.0后已经弃用了,因为确实用处不大,而且像undo、redo和binlog在查询语句中是不会写入的。

    image-20210114140554761

    查询语句

    img

    建立连接

    mysql> select * from T where ID=10;
    

    以如上的一条SQL语句为例,MySQL是采用可拔插是存储引擎,常见的存储引擎有MyISAM、InnoDB、Memory等。

    咱们之前写Java代码的时候,一般会引入一个MySQL的jdbc jar包,例如mysql-connector-java-xxx.jar,这个jar包的作用就是与MySQL的服务建立连接。

    说完连接后,就可以引出连接池的概念。从字面的意思就可以看出,这样是一个池子,因为频繁创建销毁线程对性能的影响很大,用一个池子来保持多个数据库连接,如果需要的话直接从池子里拿即可。常见的连接池有C3P0、Druid等。

    查询缓存

    查询缓存在8.0后就已经弃用了,原因是因为缓存的失效非常频繁,当对一个表更新后,那么所有的缓存都会失效。

    解析器

    解析器就是对整条SQL语句对词句分析,例如语法是否正确,当有错误的语法后就会收到下方的提示

    mysql> elect * from t where ID=1;
    
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1
    

    优化器

    一条SQL语句可能有多个执行方案,优化器的作用就是选择一个最优的方案

    mysql> select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;
    

    例如上方的语句,可能存在两种方案,可能是先查询t1的数据或者是t2的数据,具体就是优化器所需要进行的选择

    执行器

    执行器会根据我们的优化器生成的一套执行计划,然后不停的调用存储引擎的各种接口去完成SQL语句的执行计划。执行完毕后将结果返回,那么整条查询语句的过程也就结束。

    更新语句

    mysql> update T set c=c+1 where ID=2;
    

    更新语句与上方的查询语句略有不同,首先需要引入一个Buffer Pool的概念

    缓冲池

    InnoDb存储引擎的内存结构是以页为单位的,它会从磁盘上加载部分数据到缓冲池中,这样当一条更新语句来的时候,它会先查看缓冲池中是否有数据,没有的话再从硬盘上加载。这个bufferpool后边会单独认真写一篇

    image-20210114160237452

    undo log

    undo日志的作用就是在更新前将数据的旧值写入undo日志中,这样如果提交事务前需要对数据回滚的话,随时可以回滚数据。

    image-20210114162104317

    redo log buffer和redo log

    redo log buffer是内存的一个缓冲区,用来存放redo log的。redo log记录了对数据库具体做了什么操作。但是此时redo log还是在内存中,如果断电的话就会丢失。那么何时将redo log 刷新到磁盘上?

    redo log可以理解为重做日志,是InnoDB所特有的,首先就要引入一个Write-Ahead Logging概念,即先写日志,再写磁盘。redo log默认会在事务提交的时候将redolog更新到磁盘上。

    这个策略是通过innodb_flush_log_at_trx_commit来配置,这个特性也成为crash-safe。

    image-20210114163509950

    binlog

    binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。之前说redo log的时候提到提交事务的时候,会将redo日志刷新到磁盘上,其实这同时也会将binlog刷新到磁盘上。

    而binlog叫做归档日志,他里面记录的是偏向于逻辑性的日志,类似于“对users表中的id=10的一行数据做了更新操作,更新以后的值是什么”。

    基于binlog和redolog完成事务的提交

    上文提到,提交事务的时候,会同时将redo log和binlog刷入磁盘,那么为什么这么设计呢?

    因为提交binlog的时候,还会将binlog带有一个commit标记同时写入redolog中,这样的作用就是作为一个标识保证redolog和binlog的位置是一样的。

    image-20210114164425244

    当整个流程执行完后,此时磁盘上的数据还是旧值,但是缓冲池的数据却是最新的,MySQL有一个后台的IO线程,会在之后某个时间里,随机的把内存buffer pool中的修改后的脏数据给刷回到磁盘上的数据文件里去。

  • 相关阅读:
    ubuntu 源
    20121211 mysqld.sock丢失无法启动mysql和登陆
    hadoop0.20.2 & hbase0.90.1 集群启动错误“org.apache.hadoop.ipc.RPC$VersionMismatch: Protocol org.apache.hadoop.hdfs.protocol.ClientP
    20121204当前集群的几个问题
    hive中的bucket table (输入文件是一个的话,map任务只能启动一个 ,给力啊)
    Android的animation
    获取已安装程序的名字、包名
    android布局属性
    Ghost网络克隆详细步骤教程
    教你如何用PQ魔法师调整硬盘分区大小【图解教程】
  • 原文地址:https://www.cnblogs.com/xpang0/p/14472605.html
Copyright © 2011-2022 走看看