前言
这次新开了一个集体的mysql专栏,专门用于总结mysql的一些细节以及相干的案例总结,同时也包含了一些mysql的底层实现,在后续的篇章则是依据《mysql技术底细innodb存储引擎》(第二版)来深刻理解mysql中用的最多的存储引擎的外部细节。
什么是数据库驱动?
mysql的驱动置信每一个做开发的人员都很相熟,在通常的状况下咱们只须要引入一个mysql的依赖同时应用jdbc的模板代码就能实现一次mysql的连贯。
一次网络连接必须要让线程来进行解决
毫无疑问,一次网络连接不论是在tomcat还是在mysql的外部都是通过一个独自的线程进行治理的,当然tomcat的线程和mysql的线程没有任何的关系。
咱们通常状况下都是间接应用tomcat的servlet Api进行开发,同时Servlet的每一次拜访都是一个独自的线程,意味着每个用户的拜访都是互相隔离的,然而如果咱们数据库驱动连贯是单线程的并且只能有一个用户连贯,当之前的线程还在连贯解决数据,前面的线程进行连贯那么之前的解决数据的数据库连贯就会断开,这样必定是不行的,同时如果线程用完之后就被抛弃,这样也会造成资源的节约甚至有可能呈现闲暇线程明明有很多然而零碎因为某种状况无奈回收等问题,最终导致线程期待数据库的连贯申请等问题,基于这些问题数据库有了连接池的概念。
数据库连接池
连接池的作用就是维持数据库当中多个数据库连贯,当有线程拜访的时候就会从连接池当中调配一个连贯给对应的线程。另外mysql架构当中的第一个重要体系概念就是连接池,值得注意的是连接池并不是单方面的的,而是在连贯方和mysql数据库驱动方都会存在一个数据库的连接池。
依据下面的介绍,咱们绘制出上面的一张图,能够看到其实在tomcat的外部以及mysql服务器的外部都有一个对应的连接池进行对应,有了数据库连接池之后,每一个用户解决完数据库的申请会把线程归还给线程池,这样不仅进步了线程的复用率又保障了每一个用户的数据库连贯和操作是独立的。
疑难:1. mysql数据库连接池最多能够开启多少个连贯?2. 如何管制mysql的连接数?解答:1、查看最大连接数show variables like '%max_connections%';然而这里有一个参数叫做 'max_user_connections'的参数,这个参数和'max_connections'有什么关系呢?max_connections 是指整个mysql服务器的最大连接数;max_user_connections 是指每个MySQL用户的最大连接数2、批改最大连接数set GLOBAL max_connections = 200;
mysql的根本构造
上面咱们来看下mysql的根本构造是什么,从外层来看,整个申请的解决仿佛都是在mysql服务器外面进行解决,然而实际上mysql设计必定不会这样简略,在mysql的外部,他会被拆分为上面这几个组件:
sql解析器:解析用户发来的sql语言,负责剖析语法,对于sql语句进行拆解等相干操作。
查问优化器:查问优化器负责解析之后的sql语法进行逻辑的优化,保障sql能够依照最短门路来执行
存储引擎:存储引擎是用于真正执行sql的组件,存储引擎依照sql语句进行内存和硬盘上的数据更新操作。同时应用对外的接口进行操作。
执行器:执行器就是负责真正调用存储引擎上接口的组件。
上面咱们依照下面的程序通过图画来形容mysql外部是如何运作的:
sql解析器:
当咱们通过tomcat发送一条申请的时候,数据库连贯会干啥,他会依据tomcat发来的查问语句,通过一个叫做sql解析器的货色进行解析,其实数据库服务器自身也不晓得这条语句干啥用的,所以sql解释器负责管理这个货色,在通过sql接口承受到申请之后,会传递个sql解析器去进行解析动作。
select id,name,age from users where id=1个查问解析器(Parser)就是负责对SQL语句进行解析的,比方对下面那个SQL语句进行一下拆解,拆解成以下几个局部: 咱们当初要从“users”表里查问数据查问“id”字段的值等于1的那行数据对查出来的那行数据要提取外面的“id,name,age”三个字段
通过下面的案例咱们能够晓得了,Sql解析其实就是合成sql语法,通过sql语法分析出具体要做什么事件。
查问优化器
既然晓得了如何解析,上面就应该理解如何进行查问优化了。查问优化器顾名思义就是对于查问的门路进行优化和抉择,比方上面的sql语句有两种抉择(当然数据库实在执行必定不是这样的,然而咱们能够含糊的了解)
- 查问id=?的记录,并且提取对应的字段
- 找到须要的三个字段的所有数据,并且从中抉择id=?的数据
查问优化器就是用来优化查问逻辑的,会用最短的查问门路对于查问进行优化。
当然这种优化是无限的,更多状况下还是要看sql语句的查问逻辑是否简单以及sql的品质是否足够好。
存储引擎
既然查问优化器还不是执行查问的中央,那么咱们接下来再来看下查问优化器解决完之后如何解决。
咱们都晓得数据库无非是由一种非凡的数据结构结构的文件罢了,只是对外提供特定的接口以及须要依照mysql的语法能力对数据进行crud,既然是操作数据,那必定逃不过硬盘和内存,既然存储引擎是间接和这个数据结构打交道的,那么通过查问优化器优化过的的查问语句必定是要交给存储引擎的,既然执行语句的操作是交给存储引擎的,换句话说就是决定如何解决sql的最终执行权在存储引擎手上。
执行器
存储引擎能够执行sql语句,然而谁来操作存储引擎的接口呢?实际上调用存储引擎接口的是执行器,执行器会依照存储引擎的接口依照肯定的逻辑对sql进行执行。那么要如何调用接口呢?执行器会依据以后的存储引擎配套一份执行打算,而后调用存储引擎实现sql的语句对于数据进行增删改查。
依据下面的介绍,咱们能够发现实际上mysql最外围的局部是 存储引擎,它是真正在做事的一个组件。所以上面将会介绍innodb存储引擎的构造:
innodb存储引擎和构造
这里跳过innodb的介绍,咱们间接来理解外部的具体构造:
缓冲池
innodb应用缓冲池来缓解磁盘操作的压力,尽量让数据的操作在内存中进行,同时应用不定时脏数据刷盘的操作将内存的数据同步到磁盘,和少数的缓存作用了解一样,在进行查问的时候如果发现命中了缓冲池则会查缓存的数据,否则查磁盘的数据。在查缓存的时候为了避免其余的线程把缓冲池的数据变脏,会对数据进行加锁的操作。
undo日志
undo日志作用和咱们平时的ctrl+z的原理是一样的,在更新数据之前innodb须要先把批改的前的数值放到undo日志外面,而后在执行后续的操作,这个undo日志也实现事务回滚的组件,理解mysql咱们都晓得数据要么在事务外面要么在事务执行之前的undo日志,一旦事务操作失败或者手动调用回滚rollback,此时mysql就须要依据undo日志的内容把数据进行回滚。
redo缓冲池和redo日志文件
redo日志翻译过去就是重做日志,他的构造相似缓冲池和硬盘的链接形式,所以从了解上来看须要看作两局部缓冲池和日志文件,整个redo的作用就是记录哪一行的数据进行了批改并且在事务提交将缓存刷新到日志文件进行同步。(说白了还是磁盘io)
理解了根本redo作用之后咱们来思考一下如果mysql服务操作数据的时候产生了数据失落的状况,会呈现什么状况?
为了解决这个问题,innodb在筹备执行事务之前会当时操作一遍redo log buffer的缓冲区,这个缓冲区用来寄存哪一行文件的那个字段被批改了,记录数据所在的地位以及改变的数据内容等。
事务没有提交,宕机了如何解决?
数据库当中每次执行一条sql都是一个事务的提交。如果数据库解体则会呈现redo日志失落的状况,时候mysql如何解决?
这个问题很简略,事务都没有提交,阐明数据压根没有批改,而且此时尽管缓冲池的数据变了,然而磁盘数据行的内容没有变,所以redo缓冲池的数据失落了也没有影响,当宕机重启复原之后将会通过undo日志把内容进行还原。
提交事务之后将redo日志写入磁盘
事务提交之后,此时redo会应用肯定的策略把redo_log_buffer 的数据刷新到磁盘文件中,能够通过一个配置:innodb_flush_log_at_trx_commit更改策略
当这个值为0的时候不会把redo_log_buffer的内容刷新到磁盘,此时如果mysql宕机,内存的文件就全副失落了:
如果把这个值设置为1:就会在事务提交胜利之后把redo缓存数据刷新到日志文件当中,并且文件当中也会存在一条你批改了xxx行那个字段的记录。
如果此时缓冲池的内容更新了,redo日志的内容也更新了,redo文件外面的内容也记录了记录的批改内容,此时mysql忽然宕机了会导致磁盘文件的磁盘数据的不统一么?
必定不会的,如果此时一旦宕机,缓冲池就会去redo日志复原之前的批改操作如果innodb_flush_log_at_trx_commit 设置为2,会是什么状况?
此时提交事务的时候会把redo日志写到os cache外面,而不是写入磁盘,可能会是1秒之后才会把os cache的数据写入到磁盘文件。
然而此时须要留神这个日志文件是在cache外面的,所以意味着一旦宕机os cache的日志内容也没了。
三种redo日志刷盘策略到底抉择哪一种?
提交事务的时候,咱们对redo日志的刷盘策略应该抉择哪一种?每一种刷 盘策略的优缺点别离是什么?为什么?
如果对于数据特殊要求个别状况下选1就能够了,如果选0,mysql一旦宕机就生效了,如果选2,同样尽管数据是写入到零碎缓存的当中。然而还是在内存外面,只有断电宕机,数据同样会失落。
Binlog 日志
咱们先看下binlog日志在整个mysql执行过程中的过程步骤:
Bin log 日志是什么
在具体介绍之前,咱们还是从redo log开始,redo log能够看作是保障事务一致性和数据正确的外围组件,在事务提交之前会将提交记录写入到redo log避免mysql宕机失落数据的问题。
然而这一切都是基于存储引擎innodb解决的,其实在存储引擎的前一步执行器也有一个日志,那就是 bin log日志。
论断:Binlog 是属于 mysql server中执行器实现事务的重要内容。
binlog的工作流程
其实就是innodb存储引擎在redo log 筹备好数据并且刷新到磁盘之后,执行器会把数据写入到一个binlog的日志文件进行存储。
执行器是十分外围的组件,须要配合存储引擎进行一个sql在磁盘和内存的全副操作。
binlog的刷盘策略
要害参数:sync_binlog 管制刷盘策略,默认值为0。bin写入磁盘之后,不是间接进入文件,而是和redo_log的参数设置2一样(innodb_flush_log_at_trx_commit = 2)写入到os缓冲池当中,当然会呈现宕机的时候失落缓冲池数据的问题。
如上图所示的5,6开始,就是你提交事务的阶段了。此时如果产生宕机,会和之前的redo_log 一样失落内存的文件。
如果把 sync_binlog参数设置为1,则会呈现在提交事务的时候,强制把缓冲的数据刷新到binlog磁盘外面。
写入commit标记
为什么有了redo_log 还须要binlog呢?
整个事务须要在binlog 实现了文件和写入到地位记录之后并且在redolog外面写入commit标记之后才进行解决。所以有了binlog之后,能保障整个事务的最终一致性和完整性。
redolog外面写入commit标记有什么意义?
实质上是为了保障redolog和binlog一致性用的。
相干面试题
【腾讯二面】5s内建设多少个mysql连贯?:https://blog.51cto.com/u_15127515/2684815
总结
咱们从数据库的驱动介绍开始,介绍了整个mysql的工作流程,同时介绍了innodb存储引擎的工作流程,最初咱们介绍了执行器的一个要害日志binlog日志的作用以及理论的运行成果。
写在最初
下一节将会依据一些生产的案例来看看如何进行mysql的优化。