目录

1.学习目标

2.一条查询 SQL 语句是如何执行的?

2.1 通信协议

2.2 查询缓存

2.3. 语法解析和预处理(Parser & Preprocessor)

2.4 查询优化(Query Optimizer)与查询执行计划

2.5. 存储引擎

2..6. 执行引擎(Query Execution Engine),返回结果

3. MySQL 体系结构总结

3.1. 模块详解

3.2. 架构分层

4. 一条更新 SQL 是如何执行的?

4.1. 缓冲池 Buffer Pool

4.2. InnoDB 内存结构和磁盘结构

4.3. Binlog


1.学习目标

1、了解MySQL语句的执行流程
2、理解MySQL的架构与内部模块
3、掌握InnoDB存储引擎的磁盘与内存结构

2.一条查询 SQL 语句是如何执行的?

我们的程序或者工具要操作数据库,第一步要做什么事情?
跟数据库建立连接。

2.1 通信协议

在我们开发系统跟第三方对接的时候,必须要弄清楚的有两件事。第一个就是通信协议,比如我们是用HTTP还WebService还是TCP?第二个是消息格式,比如我们用XML格式,还是JSON格式,还是定长格式?报文头长度多少,包含什么内容,每个字段的详细含义。

(1)通信协议

MySQL是支持多种通信协议的,可以使用同步/异步的方式,支持长连接/短连接。
这里我们拆分来看。第一个是通信类型。

通信类型:同步或者异步

同步通信的特点:
1、同步通信依赖于被调用方,受限于被调用方的性能。也就是说,应用操作数据库,线程会阻塞,等待数据库的返回。
2、一般只能做到一对一,很难做到一对多的通信。

异步跟同步相反:
1、异步可以避免应用阻塞等待,但是不能节省SQL执行的时间。
2、如果异步存在并发,每一个SQL的执行都要单独建立一个连接,避免数据混乱。但是这样会给服务端带来巨大的压力(一个连接就会创建一个线程,线程间切换会占用大量CPU资源)。另外异步通信还带来了编码的复杂度,所以一般不建议使用。如果要
异步,必须使用连接池,排队从连接池获取连接而不是创建新连接。

一般来说我们连接数据库都是同步连接。

连接方式:长连接或者短连接

MySQL既支持短连接,也支持长连接。短连接就是操作完毕以后,马上close 掉。长连接可以保持打开,减少服务端创建和释放连接的消耗,后面的程序访问的时候还可以使用这个连接。一般我们会在连接池中使用长连接。

保持长连接会消耗内存。长时间不活动的连接,MySQL服务器会断开。

showg lobal variables like'wait_timeout'; -- 非交互式超时时间,如 JDBC 程序;
show global variables like'interactive_timeout'; -- 交互式超时时间,如数据库工具

默认都是28800秒,8小时。

我们怎么查看MySQL当前有多少个连接?
可以用show status命令:

show global status like'Thread%';

Threads_cached:

缓存中的线程连接数。

Threads_connected:

当前打开的连接数。

Threads_created:

为处理连接创建的线程数。

Threads_running:

非睡眠状态的连接数,通常指并发连接数。

Threadpool_idle_threads:

-- 表示线程池中的空闲线程数。

Threadpool_threads:

-- 表示线程池中的所有线程数。

Threads_rejected :

--?

每产生一个连接或者一个会话,在服务端就会创建一个线程来处理。反过来,如果要杀死会话,就是Kill线程。

有了连接数,怎么知道当前连接的状态?
也可以使用 SHOW PROCESSLIST; (root用户)查看SQL的执行状态

Sleep

线程正在等待客户端,以向它发送一个新语句

Query

线程正在执行查询或往客户端发送数据

Locked

该查询被其它查询锁定

Copying to tmp tableondisk

临时结果集合大于 tmp_table_size。线程把临时表从存储器内部格式改 变为磁盘模式,以节约存储器

Sending data

线程正在为 SELECT 语句处理行,同时正在向客户端发送数据

Sorting for group

线程正在进行分类,以满足 GROUPBY 要求

Sorting for order

线程正在进行分类,以满足 ORDERBY 要求

MySQL服务允许的最大连接数是多少呢?
在5.7版本中默认是151个,最大可以设置成16384(2^14)。

show variables like 'max_connections'   -- MySQL服务允许的最大连接数

show的参数说明:
1、级别:会话session级别(默认);全局global级别
2、动态修改:set,重启后失效;永久生效,修改配置文件/etc/my.cnf

set global max_connections=1000;

通信协议
MySQL支持哪些通信协议呢?
第一种是Unix Socket。

比如我们在Linux服务器上,如果没有指定-h参数,它就用socket方式登录(省略了-S /var/lib/mysql/mysql.sock)。它不用通过网络协议,也可以连接到MySQL的服务器,它需要用到服务器上的一个物理文件(/var/lib/mysql/mysql.sock)。

select@@socket;

如果指定-h参数,就会用第二种方式,TCP/IP协议。

mysql-h192.168.8.211-uroot-p123456我们的编程语言的连接模块都是用 TCP 协议连接到 MySQL 服务器的,比如mysql-connector-java-x.x.xx.jar。
       另外还有命名管道(NamedPipes)和内存共享(ShareMemory)的方式,这两种通信方式只能在Windows上面使用,一般用得比较少。

通信方式

单工:在两台计算机通信的时候,数据的传输是单向的。生活中的类比:遥控器。
     半双工:在两台计算机之间,数据传输是双向的,你可以给我发送,我也可以给你发送,但是在这个通讯连接里面,同一时间只能有一台服务器在发送数据,也就是你要给我发的话,也必须等我发给你完了之后才能给我发。生活中的类比:对讲机。
    全双工:数据的传输是双向的,并且可以同时传输。生活中的类比:打电话。

MySQL使用了半双工的通信方式。

2.2 查询缓存

MySQL内部自带了一个缓存模块。缓存的作用我们应该很清楚了,把数据以KV的形式放到内存里面,可以加快数据的读取速度,也可以减少服务器处理的时间。但是MySQL的缓存我们好像比较陌生,从来没有去配置过,也不知道它什么时候生效?
比如user_innodb有500万行数据,没有索引。我们在没有索引的字段上执行同样的查询,大家觉得第二次会快吗

select * from t_user where name='张三';

缓存没有生效,为什么?MySQL的缓存默认是关闭的。

show variables like 'query_cache%';  -- 查询缓存开关

默认关闭的意思就是不推荐使用,为什么MySQL不推荐使用它自带的缓存呢?主要是因为MySQL自带的缓存的应用场景有限,第一个是它要求SQL语句必须一模一样,中间多一个空格,字母大小写不同都被认为是不同的的SQL。第二个是表里面任何一条数据发生变化的时候,这张表所有缓存都会失效,所以对于有大量数据更新的应用,也不适合。所以缓存这一块,我们还是交给ORM框架(比如MyBatis默认开启了一级缓存),或者独立的缓存服务,比如Redis来处理更合适。在MySQL 8.0中,查询缓存已经被移除了。

2.3. 语法解析和预处理(Parser & Preprocessor)

词法解析

词法分析就是把一个完整的SQL语句打碎成一个个的单词。比如一个简单的SQL语句

select name from user whereid=1;

它会打碎成8个符号,每个符号是什么类型,从哪里开始到哪里结束。

语法解析

第二步就是语法分析,语法分析会对SQL做一些语法检查,比如单引号有没有闭合,然后根据MySQL定义的语法规则,根据SQL语句生成一个数据结构。这个数据结构我们把它叫做解析树(select_lex)。

任何数据库的中间件,比如Mycat,Sharding-JDBC(用到了Druid Parser),都必须要有词法和语法分析功能,在市面上也有很多的开源的词法解析的工具(比如LEX,Yacc)。

预处理器

解析SQL的环节里面有个预处理器。它会检查生成的解析树,解决解析器无法解析的语义。比如,它会检查表和列名是否存在,检查名字和别名,保证没有歧义。预处理之后得到一个新的解析树。

2.4 查询优化(Query Optimizer)与查询执行计划

 1.什么是优化器?

一条SQL语句是可以有很多种执行方式的,最终返回相同的结果,他们是等价的。但是如果有这么多种执行方式,这些执行方式怎么得到的?最终选择哪一种去执行?根据什么判断标准去选择?这个就是MySQL的查询优化器的模块(Optimizer)。
       查询优化器的目的就是根据解析树生成不同的执行计划(ExecutionPlan),然后选择一种最优的执行计划,MySQL里面使用的是基于开销(cost)的优化器,那种执行计划开销最小,就用哪种。

可以使用这个命令查看查询的开销:

show status like 'Last_query_cost';

2. 优化器可以做什么?

实际上,对于每一种数据库来说,优化器的模块都是必不可少的,他们通过复杂的算法实现尽可能优化查询效率的目标。

但是优化器也不是万能的,并不是再垃圾的SQL语句都能自动优化,也不是每次都能选择到最优的执行计划,大家在编写SQL语句的时候还是要注意。

3. 优化器是怎么得到执行计划的?

首先我们要启用优化器的追踪(默认是关闭的):

SHOW VARIABLES LIKE 'optimizer_trace';

set optimizer_trace = 'enabled=on';

注意开启这开关是会消耗性能的,因为它要把优化分析的结果写到表里面,所以不要轻易开启,或者查看完之后关闭它(改成off)。注意:参数分为session和global级别。接着我们执行一个SQL语句,优化器会生成执行计划:

select t.tcid from teache rt,teacher_contact t c where t.tcid=tc.tcid;

这个时候优化器分析的过程已经记录到系统表里面了,我们可以查询

select * from information_schema.optimizer_trace\G

它是一个JSON类型的数据,主要分成三部分,准备阶段、优化阶段和执行阶段。

expanded_query是优化后的SQL语句。
considered_execution_plans里面列出了所有的执行计划。
分析完记得关掉它:

set optimizer_trace = "enabled=off";

SHOW VARIABLES LIK E'optimizer_trace';

4. 优化器得到的结果

优化器最终会把解析树变成一个查询执行计划,查询执行计划是一个数据结构。MySQL提供了一个执行计划的工具。我们在SQL语句前面加上EXPLAIN,就可以看到执行计划的信息。

EXPLAIN select name from user whereid=1;

*注意Explain的结果也不一定最终执行的方式。

2.5. 存储引擎

1.存储引擎基本介绍

我们可以把这个表理解成Excel电子表格的形式。所以我们的表在存储数据的同时,还要组织数据的存储结构,这个存储结构就是由我们的存储引擎决定的,所以我们也可以把存储引擎叫做表类型。

在MySQL里面,支持多种存储引擎,他们是可以替换的,所以叫做插件式的存储引擎。

2.查看存储引擎

在MySQL里面,我们创建的每一张表都可以指定它的存储引擎,而不是一个数据库只能使用一个存储引擎。存储引擎的使用是以表为单位的。而且,创建表之后还可以修改存储引擎。
       我们说一张表使用的存储引擎决定我们存储数据的结构,那在服务器上它们是怎么存储的呢?我们先要找到数据库存放数据的路径。

show variables like 'datadir';

默认情况下,每个数据库有一个自己文件夹,任何一个存储引擎都有一个frm文件,这个是表结构定义文件。

不同的存储引擎存放数据的方式不一样,产生的文件也不一样,innodb 是 1 个,memory没有,myisam是两个。

3.存储引擎比较

MyISAM 和InnoDB 是我们用得最多的两个存储引擎,在 MySQL 5.5 版本之前,默认的存储引擎是MyISAM,它是MySQL自带的。我们创建表的时候不指定存储引擎,它就会使用MyISAM作为存储引擎。MyISAM的前身是ISAM(IndexedSequentialAccessMethod:利用索引,顺序存取数据的方法)。
         5.5版本之后默认的存储引擎改成了InnoDB,它是第三方公司为MySQL开发的。为什么要改呢?最主要的原因还是InnoDB 支持事务,支持行级别的锁,对于业务一致性要求高的场景来说更适合。

数据库支持的存储引擎
我们可以用这个命令查看数据库对存储引擎的支持情况:

show  engines;

其中有存储引擎的描述和对事务、XA协议和Savepoints的支持。XA协议用来实现分布式事务(分为本地资源管理器,事务管理器)。Savepoints用来实现子事务(嵌套事务)。创建了一个Savepoints之后,事务就可以回滚到这个点,不会影响到创建Savepoints之前的操作。

MyISAM(3 个文件)

应用范围比较小。表级锁定限制了读/写的性能,因此在Web 和数据仓库配置中,它通常用于只读或以读为主的工作。
特点:
     支持表级别的锁(插入和更新会锁表)。不支持事务。
     拥有较高的插入(insert)和查询(select)速度。
     存储了表的行数(count速度更快)。
  (怎么快速向数据库插入100万条数据?我们有一种先用MyISAM插入数据,然后修改存储引擎为InnoDB的操作。)
适合:只读之类的数据分析的项目。

InnoDB(2 个文件)

mysql5.7中的默认存储引擎。 InnoDB是一个事务安全(与ACID兼容)的MySQL存储引擎,它具有提交、回滚和崩溃恢复功能来保护用户数据。InnoDB行级锁(不升级为更粗粒度的锁)和Oracle风格的一致非锁读提高了多用户并发性和性能。InnoDB将
用户数据存储在聚集索引中,以减少基于主键的常见查询的I/O。为了保持数据完整性,InnoDB还支持外键引用完整性约束。
特点:
     支持事务,支持外键,因此数据的完整性、一致性更高。
     支持行级别的锁和表级别的锁。
     支持读写并发,写不阻塞读(MVCC)。
    特殊的索引存放方式,可以减少IO,提升查询效率。
适合:经常更新的表,存在并发读写或者有事务处理的业务系统。

此外,mysql中常见的引擎还有Memory,CSV,Archive,此处不做一一对比。

2.6. 执行引擎(Query Execution Engine),返回结果

OK,存储引擎分析完了,它是我们存储数据的形式,继续第二个问题,是谁使用执行计划去操作存储引擎呢?
这就是我们的执行引擎,它利用存储引擎提供的相应的API来完成操作。为什么我们修改了表的存储引擎,操作方式不需要做任何改变?因为不同功能的存储引擎实现的API是相同的。最后把数据返回给客户端,即使没有结果也要返回。

3. MySQL 体系结构总结

3.1. 模块详解

1、 Connector:用来支持各种语言和SQL的交互,比如PHP,Python,Java的JDBC;
2、 Management Serveices & Utilities:系统管理和控制工具,包括备份恢复、MySQL复制、集群等等;
3、 Connection Pool:连接池,管理需要缓冲的资源,包括用户密码权限线程等等;
4、 SQL Interface:用来接收用户的SQL命令,返回用户需要的查询结果
5、 Parser:用来解析SQL语句;
6、 Optimizer:查询优化器;
7、 CacheandBuffer:查询缓存,除了行记录的缓存之外,还有表缓存,Key缓存,权限缓存等等;
8、 Pluggable Storage Engines:插件式存储引擎,它提供API给服务层使用,跟具体的文件打交道

3.2. 架构分层

总体上,我们可以把MySQL分成三层,跟客户端对接的连接层,真正执行操作的服务层,和跟硬件打交道的存储引擎层(参考MyBatis:接口、核心、基础)。

1.连接层

我们的客户端要连接到MySQL服务器3306端口,必须要跟服务端建立连接,那么管理所有的连接,验证客户端的身份和权限,这些功能就在连接层完成。

2.服务层

连接层会把SQL语句交给服务层,这里面又包含一系列的流程:比如查询缓存的判断、根据SQL调用相应的接口,对我们的SQL语句进行词法和语法的解析(比如关键字怎么识别,别名怎么识别,语法有没有错误等等)。然后就是优化器,MySQL底层会根据一定的规则对我们的 SQL语句进行优化,最后再交给执行器去执行。

3.存储引擎

存储引擎就是我们的数据真正存放的地方,在MySQL里面支持不同的存储引擎。再往下就是内存或者磁盘。

4. 一条更新 SQL 是如何执行的?

在数据库里面,我们说的update操作其实包括了更新、插入和删除。如果大家有看过MyBatis的源码,应该知道Executor里面也只有doQuery()和doUpdate()的方法,没有doDelete()和doInsert()。更新流程和查询流程有什么不同呢?基本流程也是一致的,也就是说,它也要经过解析器、优化器的处理,最后交给执行器。区别就在于拿到符合条件的数据之后的操作。

4.1. 缓冲池 Buffer Pool

首先,InnnoDB的数据都是放在磁盘上的,InnoDB操作数据有一个最小的逻辑单位,叫做页(索引页和数据页)。我们对于数据的操作,不是每次都直接操作磁盘,因为磁盘的速度太慢了。

InnoDB使用了一种缓冲池的技术,也就是把磁盘读到的页放到一块内存区域里面。这个内存区域就叫Buffer Pool。

下一次读取相同的页,先判断是不是在缓冲池里面,如果是,就直接读取,不用再次访问磁盘。修改数据的时候,先修改缓冲池里面页。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。InnoDB里面有专门的后台线程把Buffer Pool的数据写入到磁盘,每隔一段时间就一次性地把多个修改写入磁盘,这个动作就叫做刷脏。BufferPool是InnoDB里面非常重要的一个结构,它的内部又分成几块区域。这里我们趁机到官网来认识一下InnoDB的内存结构和磁盘结构。

4.2. InnoDB 内存结构和磁盘结构

1.内存结构

Buffer Pool 主要分为 3 个部分: Buffer Pool、Change Buffer、Adaptive HashIndex,另外还有一个(redo)log buffer。

Buffer Pool
Buffer Pool缓存的是页面信息,包括数据页、索引页。
查看服务器状态,里面有很多跟Buffer Pool相关的信息:

SHOW STATUS LIKE '%innodb_buffer_pool%';

这些状态都可以在官网查到详细的含义,用搜索功能。 https://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html

Buffer Pool默认大小是128M(134217728字节),可以调整。
查看参数(系统变量)

SHOW VARIABLES like '%innodb_buffer_pool%';

这些参数都可以在官网查到详细的含义,用搜索功能。 https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html

内存的缓冲池写满了怎么办?(Redis 设置的内存满了怎么办?)InnoDB 用 LRU算法来管理缓冲池(链表实现,不是传统的LRU,分成了young和old),经过淘汰的数据就是热点数据。

内存缓冲区对于提升读写性能有很大的作用。思考一个问题:当需要更新一个数据页时,如果数据页在BufferPool中存在,那么就直接更新好了。否则的话就需要从磁盘加载到内存,再对内存的数据页进行操作。也就是说,如果没有命中缓冲池,至少要产生一次磁盘IO,有没有优化的方式呢?

Change Buffer 写缓冲

如果这个数据页不是唯一索引,不存在数据重复的情况,也就不需要从磁盘加载索引页判断数据是不是重复(唯一性检查)。这种情况下可以先把修改记录在内存的缓冲池中,从而提升更新语句(Insert、Delete、Update)的执行速度。这一块区域就是 Change Buffer。5.5 之前叫Insert Buffer 插入缓冲,现在也能支持delete和update。

最后把 Change Buffer 记录到数据页的操作叫做 merge。什么时候发生 merge?有几种情况:在访问这个数据页的时候,或者通过后台线程、或者数据库shut down、redo log写满时触发。如果数据库大部分索引都是非唯一索引,并且业务是写多读少,不会在写数据后立刻读取,就可以使用Change Buffer(写缓冲)。写多读少的业务,调大这个值:

SHOW  VARIABLES  LIKE  'innodb_change_buffer_max_size';

代表Change Buffer占Buffer Pool的比例,默认25%。

Adaptive Hash Index
        索引应该是放在磁盘的,为什么要专门把一种哈希的索引放到内存?下一篇中会讲到。

(redo)Log Buffer

思考一个问题:如果BufferPool里面的脏页还没有刷入磁盘时,数据库宕机或者重启,这些数据丢失。如果写操作写到一半,甚至可能会破坏数据文件导致数据库不可用。为了避免这个问题, InnoDB把所有对页面的修改操作专门写入一个日志文件,并且
在数据库启动时从这个文件进行恢复操作(实现crash-safe)——用它来实现事务的持久性。

这个文件就是磁盘的redo log(叫做重做日志),对应于/var/lib/mysql/目录下的ib_logfile0和ib_logfile1,每个48M。这种日志和磁盘配合的整个过程,其实就是 MySQL 里的 WAL 技术(Write-Ahead Logging),它的关键点就是先写日志,再写磁盘。

show variables like 'innodb_log%';

问题:
同样是写磁盘,为什么不直接写到db file里面去?为什么先写日志再写磁盘?
我们先来了解一下随机I/O和顺序I/O的概念。
磁盘的最小组成单元是扇区,通常是512个字节。
操作系统和内存打交道,最小的单位是页Page。
操作系统和磁盘打交道,读写磁盘,最小的单位是块Block。

如果我们所需要的数据是随机分散在不同页的不同扇区中,那么找到相应的数据需要等到磁臂旋转到指定的页,然后盘片寻找到对应的扇区,才能找到我们所需要的一块数据,一次进行此过程直到找完所有数据,这个就是随机IO,读取数据速度较慢。

假设我们已经找到了第一块数据,并且其他所需的数据就在这一块数据后边,那么就不需要重新寻址,可以依次拿到我们所需的数据,这个就叫顺序IO。

刷盘是随机I/O,而记录日志是顺序I/O,顺序I/O效率更高。因此先把修改写入日志,可以延迟刷盘时机,进而提升系统吞吐。

当然redo log也不是每一次都直接写入磁盘,在Buffer Pool里面有一块内存区域(Log Buffer)专门用来保存即将要写入日志文件的数据,默认16M,它一样可以节省磁盘IO。

SHOW VARIABLES LIKE 'innodb_log_buffer_size';

需要注意: redolog的内容主要是用于崩溃恢复。磁盘的数据文件,数据来自bufferpool。redo log写入磁盘,不是写入数据文件。那么,Log Buffer什么时候写入log file?在我们写入数据到磁盘的时候,操作系统本身是有缓存的。flush就是把操作系统缓冲区写入到磁盘。

log buffer写入磁盘的时机,由一个参数控制,默认是1。

SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';

https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

这是内存结构的第4块内容,redo log,它又分成内存和磁盘两部分。redo log有什么特点?

1、redo log是InnoDB存储引擎实现的,并不是所有存储引擎都有。
2、不是记录数据页更新之后的状态,而是记录这个页做了什么改动,属于物理日志。
3、redo log的大小是固定的,前面的内容会被覆盖。

checkpoint是当前要覆盖的位置。如果writepos跟checkpoint重叠,说明redlog已经写满,这时候需要同步redo log到磁盘中。

这是MySQL的内存结构,总结一下,分为:Buffer pool、change buffer、Adaptive Hash Index、 log buffer。
磁盘结构里面主要是各种各样的表空间,叫做Table space。

2.磁盘结构

表空间可以看做是InnoDB 存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。InnoDB的表空间分为5大类。

在默认情况下 InnoDB 存储引擎有一个共享表空间(对应文件/var/lib/mysql/ibdata1),也叫系统表空间。

InnoDB系统表空间包含InnoDB数据字典和双写缓冲区,ChangeBuffer和UndoLogs),如果没有指定file-per-table,也包含用户创建的表和索引数据。

1、undo在后面介绍,因为有独立的表空间。
2、数据字典:由内部系统表组成,存储表和索引的元数据(定义信息)。
3、双写缓冲(InnoDB的一大特性):

InnoDB的页和操作系统的页大小不一致,InnoDB页大小一般为16K,操作系统页大小为4K,InnoDB的页写入到磁盘时,一个页需要分4次写。

如果存储引擎正在写入页的数据到磁盘时发生了宕机,可能出现页只写了一部分的情况,比如只写了4K,就宕机了,这种情况叫做部分写失效(partialpagewrite),可能会导致数据丢失。

show variables like 'innodb_doublewrite';

我们不是有redolog吗?但是有个问题,如果这个页本身已经损坏了,用它来做崩溃恢复是没有意义的。所以在对于应用redolog之前,需要一个页的副本。如果出现了写入失效,就用页的副本来还原这个页,然后再应用redolog。这个页的副本就是doublewrite,InnoDB的双写技术。通过它实现了数据页的可靠性。

跟redo log 一样,double write 由两部分组成,一部分是内存的double write,一个部分是磁盘上的doublewrite。因为doublewrite是顺序写入的,不会带来很大的开销。在默认情况下,所有的表共享一个系统表空间,这个文件会越来越大,而且它的空间不会收缩。

独占表空间 file-per-table tablespaces

我们可以让每张表独占一个表空间。这个开关通过innodb_file_per_table设置,默认开启。

SHOW VARIABLES LIKE 'innodb_file_per_table';

开启后,则每张表会开辟一个表空间,这个文件就是数据目录下的 ibd文件(例如/var/lib/mysql/gupao/user_innodb.ibd),存放表的索引和数据。但是其他类的数据,如回滚(undo)信息,插入缓冲索引页、系统事务信息,二次写缓冲(Double write buffer)等还是存放在原来的共享表空间内。

通用表空间 general tablespaces

通用表空间也是一种共享的表空间,跟ibdata1类似。
可以创建一个通用的表空间,用来存储不同数据库的表,数据路径和文件可以自定义。语法:

create tablespace ts2673 add datafile '/var/lib/mysql/ts2673.ibd' file_block_size=16K engine=innodb;

在创建表的时候可以指定表空间,用ALTER修改表空间可以转移表空间。

create table t2673(id integer) tablespace ts2673;

不同表空间的数据是可以移动的。
删除表空间需要先删除里面的所有表。

drop table t2673;

drop tablespace ts2673

临时表空间 temporary tablespaces

存储临时表的数据,包括用户创建的临时表,和磁盘的内部临时表。对应数据目录下的ibtmp1文件。当数据服务器正常关闭时,该表空间被删除,下次重新产生。

Redo log

磁盘结构里面的redo log,在前面已经介绍过了。

undo log tablespace

https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-tablespaces.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-logs.html

undolog(撤销日志或回滚日志)记录了事务发生之前的数据状态(不包括select) 。如果修改数据时出现异常,可以用undo log来实现回滚操作(保持原子性)。

在执行undo 的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,属于逻辑格式的日志。

redo Log和undo Log与事务密切相关,统称为事务日志。

undo Log 的数据默认在系统表空间ibdata1 文件中,因为共享表空间不会自动收缩,也可以单独创建一个undo表空间。

show global variables like'%undo%';

有了这些日志之后,我们来总结一下一个更新操作的流程,这是一个简化的过程。
name原值是张三。

update user set name='李四' where id=1;

1、事务开始,从内存或磁盘取到这条数据,返回给Server 的执行器;
2、执行器修改这一行数据的值为penyuyan;
3、记录name=qingshan到undo log;
4、记录name=penyuyan到redo log;
5、调用存储引擎接口,在内存(Buffer Pool)中修改 name=penyuyan;
6、事务提交。
内存和磁盘之间,工作着很多后台线程。

3.后台线程

后台线程的主要作用是负责刷新内存池中的数据和把修改的数据页刷新到磁盘。后台线程分为:master thread,IO thread,purge thread,page cleaner thread。

master thread负责刷新缓存数据到磁盘并协调调度其它后台进程。

IOthread 分为 insert buffer、 log、 read、 write进程。分别用来处理insert buffer、重做日志、读写请求的IO回调。

purge thread用来回收undo 页。

page cleaner thread用来刷新脏页。

除了 InnoDB 架构中的日志文件,MySQL 的 Server 层也有一个日志文件,叫做binlog,它可以被所有的存储引擎使用。

4.3. Binlog

https://dev.mysql.com/doc/refman/5.7/en/binary-log.html

binlog以事件的形式记录了所有的DDL和DML语句(因为它记录的是操作而不是数据值,属于逻辑日志),可以用来做主从复制和数据恢复。跟redo log不一样,它的文件内容是可以追加的,没有固定大小限制。

在开启了binlog功能的情况下,我们可以把binlog导出成SQL语句,把所有的操作重放一遍,来实现数据的恢复。binlog的另一个功能就是用来实现主从复制,它的原理就是从服务器读取主服务器的binlog,然后执行一遍。

有了这两个日志之后,我们来看一下一条更新语句是怎么执行的:

例如一条语句:update teacher set name='令狐冲' where id=1;

1、先查询到这条数据,如果有缓存,也会用到缓存。

2、把name改成盆鱼宴,然后调用引擎的API接口,写入这一行数据到内存,同时记录redo log。这时 redo log 进入prepare 状态,然后告诉执行器,执行完成了,可以随时提交。

3、 执行器收到通知后记录binlog,然后调用存储引擎接口, 设置redolog为commit状态。

4、更新完成。

这张图片的重点

1、先记录到内存,再写日志文件。

2、记录redo log分为两个阶段。

3、存储引擎和Server记录不同的日志。

3、先记录redo,再记录binlog。

2.mysql底层架构和sql执行流程相关推荐

  1. MySQL系列---架构与SQL执行流程详解

    文章目录 1. 背景 2. 架构体系 2.1 架构图 2.2 模块详解 2.3 架构分层 3. 查询SQL语句执行流程 3.1 连接 3.1.1 MySQL支持的通信协议 3.1.2 通信方式 3.2 ...

  2. mysql执行sql流程_MySQL架构与SQL执行流程

    MySQL架构设计 下面是一张MySQL的架构图: 上方各个组件的含义如下: Connectors 指的是不同语言中与SQL的交互 Management Serveices & Utiliti ...

  3. MySQL 架构与 SQL 执行流程

    使用的mysql是5.7版本 1. 一条查询 SQL 语句是如何执行的? 程序或者工具要操作数据库,第一步要跟数据库建立连接. 1.1. 通信协议 首先,MySQL 必须要运行一个服务,监听默认的端口 ...

  4. [06][03][01] MySQL架构与SQL执行流程

    文章目录 1. 一条 SQL 语句执行步骤 1.1 通信 1.1.1 通信类型 1.1.2 连接方式 1.1.3 通信协议 1.1.4 通信方式 1.2 查询缓存 1.3 语法解析和预处理 (Pars ...

  5. 步步深入MySQL:架构-gt;查询执行流程-gt;SQL解析顺序!

    一.前言 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序来探讨一下其中的知识. 二.MySQL架构总览 架构最好看图,再配上必要的说明文字. 下图根据参考书籍中一图为原 ...

  6. MySQL 文件结构、逻辑架构及 sql 执行流程分析作者:Java后端架构

    1.MySQL 文件说明 1.1 MySQL 文件夹文件 linux 服务器上 MySQL 安装好之后都有如下文件: auto.cnf:每一个 MySQL 实例都有一个唯一 ID 蓝色文件夹:表示数据 ...

  7. mysql表文件与结构_MySQL文件结构、逻辑架构及sql执行流程分析

    1.MySQL文件说明 1.1 MySQL文件夹文件 linux服务器上MySQL安装好之后都有如下文件: auto.cnf:每一个MySQL实例都有一个唯一ID 蓝色文件夹:表示数据库,每个数据库对 ...

  8. MySQL 整体架构与 SQL 执行原理,数据库事务原理

    起 一个查询语句的例子 在执行下面这个查询语句时的执行的流程是怎么样的? mysql> select * from t where id=1: 执行器的执行流程是这样的: 1.调用 InnoDB ...

  9. Mysql复习计划(一)- 字符集、文件系统和SQL执行流程

    Mysql复习计划(一)- 字符集.文件系统和SQL执行流程 前言 一. Mysql字符集 1.1 Mysql5.7和8.0的默认字符集 1.1.1 修改默认的字符集 1.1.2 修改已有库表的字符集 ...

最新文章

  1. 在Ubuntu/mint里安装VMware tools(虚拟机增强工具)
  2. 基于QoE的实时视频编码优化:低功耗,低延时,高质量
  3. 在Ubuntu上安装SAP Cloud Connector的一些错误
  4. Spring休眠教程
  5. java ee13_一口气了解多线程及其Java实现
  6. 让你成为有钱一族的黄金理财法则?
  7. position:relative/absolute无法冲破的等级
  8. CABAC 基础二-算术编码
  9. 拜托!面试请不要再问我Spring Cloud底层原理
  10. 有PMP证书后,如何继续成长?
  11. MAC与PHY的接口GMII RGMII SGMII Serdes
  12. 易语言群控雷电_安卓群控系统雷电模拟器安卓多开模拟器多开群控系统企业自动化的营销系统软件-资源下载随便下源码网...
  13. 数据库原理与应用(五)专门的关系运算
  14. 阿里巴巴达摩院视觉AI平台概述
  15. python爬取bilibili数据_BiliBili爬取数据简单分析
  16. 【IKAnalyzer中文分词器详解-(1)分词逻辑】
  17. 聊聊Kafka中值得我们学习的优秀设计
  18. 主板上的内存插槽颜色到底代表了什么意思?
  19. 《人性的弱点》良句收录和读后感想
  20. 【技术综述】人脸表情识别研究

热门文章

  1. 电脑不识别鼠标 不小心删了无线网卡驱动
  2. 解决maven库中没有Oracle jdbc驱动的问题Cannot resolve com.oracle:ojdbc14:10.2.0.4.0 ; 驱动下载
  3. keil c语言范例,KeilC实例代码.doc
  4. 忆327国债期货大厮杀(包括国债期货的基本原理)
  5. JS循环遍历中使用异步
  6. turtle画画 画图形
  7. python递归实现文件复制_在python中递归复制文件或目录
  8. Android单目手势识别,单目手势识别及其在安卓平台的应用研究
  9. linux全端口开放策略_Linux的影子策略,Shadwen发布日期以及更多开放游戏新闻
  10. 微信小程序用python语言开发_微信小程序语音识别开发过程笔记