MySQL服务监听的端口默认是3306✿✿,客户端连接服务端的方式有很多种✿✿。可以是异步✿✿,同步✿✿,短连接内参揭幕✿✿,长连接✿✿,可以是TCP也可以是Unix Socket✿✿。
客户端每产生一个连接或者一个会话✿✿,在服务端就会创建一个线程来处理✿✿。想要杀死会话就要Kill一个线程✿✿。
有全局(Global)和会话(Session)基本✿✿,分别作用于全局和当前会话✿✿。并不是所有参数都拥有两种作用域✿✿。比如说✿✿,max_connections就只有全局级别✿✿。
比如下面这个只是临时修改✿✿,建议修改为session级别✿✿。如果需要在其他会话中生效✿✿,必须显式加上Global参数✿✿。
使用场景极其有限欧亿体育官网✿✿,SQL语句必须一模一样✿✿,中间不允许多一个空格✿✿,而且大小写敏感✿✿;表里有任何一条数据的变化产生的时候✿✿,这张表的缓存都会失效✿✿。对于有大量数据更新的应用✿✿,也不适合✿✿;
这是由Parser解析器和Preprocessor预处理来完成的✿✿。这一步主要就是对语句基于SQL语法进行词法和语法分析语义分析✿✿。
对SQL做一些语法检查✿✿,比如单引号是否闭合✿✿,再根据MySQ定义的语法规则✿✿,根据SQL语句生成一个数据结构✿✿。叫做解析树(select_lex)✿✿。
词法语法分析✿✿,是一个非常基础的功能✿✿,Java的编译器✿✿、百度搜索引擎如果要识别语句✿✿,也必须要有词法语法分析的功能✿✿。任何数据库的中间件✿✿,要解析SQL完成路由功能欧亿体育✿✿,也必须要有词法和语法分析的功能✿✿,比如MyCat✿✿,Sharding-JDBC(Druid Parser)基础建设✿✿。在市面上也有很多的开源词法解析工具(LEX✿✿,YACC)✿✿。
问题✿✿:如果我写了一个条SQL✿✿,但是表名或者字段不存在欧亿体育官网✿✿,会在哪里报错?在数据库的执行层还是解析器?
其实还是在解析器这里报错✿✿,解析SQL的环节里面有一个预处理器✿✿。预处理器会检查生成的解析树✿✿,解决解析器无法解析的语义✿✿。检查表和列名是否存在内参揭幕✿✿,检查名字和别名✿✿,保证没有歧义✿✿。
查询优化器根据解析树生成不同的执行计划(Execution Plan)✿✿,然后选择一种最优的执行计划✿✿,MySQL里面使用的是基于开销(cost)的优化器✿✿,哪一种执行计划的开销最小✿✿,就选择哪种✿✿。
默认情况下✿✿,每个数据库都有自己的文件夹✿✿,任何一个存储引擎都有一个frm文件✿✿,这个是表结构定义文件✿✿。
一张表✿✿,需要很高的访问速度✿✿,而不需要考虑持久化问题✿✿,可以选择把数据放在内存✿✿。一张表✿✿,是用来做历史数据存档✿✿,不需要修改✿✿,也不需要索引✿✿,需要支持数据压缩等等✿✿。一张表✿✿,用于读写并发很多的业务中✿✿,是不是需要支持读写不干扰✿✿,需要保证较高的数据一致性?
支持表级别锁(插入和更新会锁表)✿✿。不支持事务✿✿。拥有较高的插入和查询速度✿✿。存储了表的行数(count速度快)✿✿。
(如何快速向数据库插入100W行数据?表的引擎先用MYISAM插入数据✿✿,然后修改引擎为INNODB操作)✿✿。
MySQL的默认引擎✿✿,INNODB是一个事务安全(acid兼容)的存储引擎✿✿,具有提交✿✿、回滚✿✿、崩溃恢复功能来保护用户数据✿✿。INNODB行级别的锁(不升级为更粗粒度的锁)和ORACLE风格一致非锁读提高了多用户并发和性能✿✿。INNODB将用户数据存储在聚集索引中✿✿,以减少基于主键的IO查询✿✿,为了保证数据完整性✿✿,INNODB还支持外键引用完整性约束✿✿。
支持事务✿✿、外键✿✿。数据的完整性欧亿体育官网✿✿,一致性高✿✿。支持行级别的锁和表级别的锁✿✿。支持读写并发✿✿,写不阻塞读(MVCC)✿✿。特殊的索引存放方式✿✿,可以减少IO✿✿,提升查询效率✿✿。
所有数据都存放于内存中✿✿,提供快速查找(非关键数据)的场景下使用✿✿。INNODB及其缓冲内存区域✿✿,提供一种通用✿✿、持久的方法将大部分数据保存在内存中✿✿,ndbcluster为大型分布式系统数据集提供了快速的键值查找✿✿。正在淘汰✿✿。
如何选择存储引擎?对数据库一致性要求较高✿✿,需要事务支持✿✿。innodb查询多更新少✿✿,对查询性能要求高✿✿。myisam用于查询的临时表✿✿。memory如果都满足不了✿✿,自己用C写一个✿✿。
客户端需要连接到MYSQL服务器3306端口✿✿,必须要跟服务端建立连接✿✿,那么管理连接和验证连接都在连接层完成✿✿。
通过连接层获得session✿✿,发送sql语句给服务层✿✿。比如查询缓存✿✿,根据SQL调用对应接口✿✿,词法解析✿✿,语法分析✿✿,执行计划✿✿,索引选择等等✿✿。然后就是优化器✿✿,得到执行计划✿✿,交给执行器去执行✿✿。
内存写向磁盘是IO操作内参揭幕✿✿,比较耗费时间✿✿,MySQL提出来一个叫缓冲区的概念✿✿,先写入缓冲区再由缓冲区写入磁盘✿✿,这个操作我们称之为刷脏✿✿。
在操作系统✿✿、存储引擎✿✿,都有一个预读概念✿✿。当磁盘上的一块数据被读取时候✿✿,其他附近位置的数据也会马上被读到✿✿,这个就叫局部性原理✿✿。INNODB设定了一个存储引擎从磁盘读取数据到内存的最小单位是页✿✿,在操作系统中页的大小为4kb✿✿,在INNODB里面这个最小的默认单位为16KB✿✿。
刷脏并不是实时的✿✿,如果Buffer Pool的脏页没有刷完✿✿,数据库宕机或者停电了✿✿,数据会丢失✿✿。这个时候引入了一个 redo log的持久化措施✿✿。
为了避免这个问题✿✿,mysql会把所有对页面修改操作专门写入一个日志文件(RedoLog)✿✿。如果有未同步到磁盘的数据✿✿,数据库会在启动的时候✿✿,从这个日志文件进行恢复操作(实现crash-safe)✿✿。我们数据库事务的持久性就是用它来实现✿✿。
磁盘的写入是需要寻址的✿✿,磁盘是一个圆欧亿体育官网✿✿,磁头固定旋转后产生磁道✿✿,然后每个磁道根据半径的划分的区域就是扇区✿✿,磁盘写入的就是需要找到这些扇区然后进行写入✿✿。如果数据是随机散落在不同的扇区✿✿,那么需要磁头旋转找到对应的数据页✿✿,然后盘片找到对应扇区才能找到一块数据✿✿,一次次进行这个过程直到找到所有数据为止✿✿。刷盘是随机IO✿✿,而记录日志是顺序IO(连续读写)✿✿,顺序IO的效率上更高✿✿。本质上就是数据集中处理和分散存储的区别✿✿。因此如果写入日志文件能够大大的保证数据的安全性✿✿,可以延迟刷盘 ✿✿,提高吞吐✿✿。
redo log是INNODB存储引擎的实现✿✿,支持崩溃恢复的INNODB的一个特性✿✿。redo log不是记录数据页更新之后的状态✿✿,而是记录”在某项数据页上做了什么修改“✿✿。属于物理日志redo log的大小是固定的✿✿,前面的内容会被覆盖✿✿,一旦写满会触发buffer pool到磁盘同步✿✿,以便腾出空间记录后面的修改欧亿体育官网✿✿。
Undo log(撤销或者回滚日志)记录了事务发生之前的数据状态✿✿,分别为 inser undo log和update undo log✿✿。如果修改数据发生异常✿✿,可以使用undo log来实现回滚✿✿。(保证原子性)
可以理解undo log记录的是反向操作✿✿,比如insert会记录delete✿✿,update 会记录update 原来的值✿✿,跟redolog记录在哪个物理页面操作不一样✿✿,所以叫做逻辑日志✿✿。
Buffer Pool缓存的是页面信息内参揭幕✿✿,包括数据页✿✿,索引页✿✿。Buffer Pool默认大小是128m✿✿。(可以调整)
这个是会问到Buffer Pool写满了怎么办(Rdis设置的内存满了怎么办?)LRU算法来管理缓冲池(链表实现✿✿,不是传统的LRU✿✿,分成了young和old)经过淘汰的数据就是热点数据✿✿。
如果buffer pool的时候发现没有空闲页了✿✿,就要从buffer pool中淘汰数据页了✿✿。
因为innodb的预读机制✿✿,数据页并不是在被访问的时候才缓存到buffer pool✿✿。设计者认为✿✿,访问某个page页的数据时候✿✿,相邻的page 可能也会很快被访问到✿✿,所以先把这些page先缓存起来✿✿。
缓存机制又分为两种类型一种叫线性预读(异步)(Linear read-ahead)✿✿。innodb 把64个相邻的page叫做一个extent区✿✿,如果顺序访问了一个extent的56个page✿✿,这个时候innodb就会把下一个extent区缓存到buffer pool中✿✿。顺序访问了多少个page 才缓存下一个extent✿✿,由一个参数控制✿✿:
一种叫随机预读(Random read-ahead)如果buffer pool✿✿,已经缓存了同一个extent区的数据页个数超过13时候✿✿,就会把这个extent剩余的所有page 全部缓存到buffer pool✿✿。但是随机预读功能是不开启的✿✿,由一个参数控制
如果buffer pool size 不是很大✿✿,而且预读的数量很多✿✿,很可能那些真正被需要缓存的数据被预读数据挤出buffer pool✿✿。
所有数据加入到buffer pool 的时候✿✿,一律放在冷区head✿✿,不管是预读还是普通读操作✿✿。所以如果预读数据没有被读取✿✿,会在old sublist冷区直接淘汰✿✿。放入LRU List以后✿✿,如果再次被访问✿✿,都会把它移动到热区的Head✿✿。如果热区的数据没有被访问✿✿,会被移动冷区head✿✿,然后慢慢被淘汰✿✿。
热区5/8✿✿,冷区3/8✿✿,这个值由innodb_old_blocks_pct控制✿✿。它代表的是old区的大小✿✿,默认是37%✿✿。如果这个值太小✿✿,old区没有被访问的数据淘汰会更快✿✿。
如果在同一时间很多冷区数据被访问欧亿体育官网✿✿,会导致大量的数据都移动到了热区✿✿,有可能会导致大量的热区数据失效✿✿。这个问题怎么解决?
加大加入冷区后的访问间隔✿✿,INNODB_OLD_BLOCKS_TIME(默认1s)这个参数来控制✿✿,加入冷区多少S后被访问才放入热区数据✿✿。
Change Buffer 是Buffer pool的一部分✿✿。如果这个数据页不是唯一索引欧亿体育官网✿✿,不存在数据重复的情况✿✿,也就不需要从磁盘判断数据是否唯一(唯一性检查)✿✿。这种情况可以先把修改记录和内存的缓存池中✿✿,从而提升(inser✿✿,delete✿✿,update)性能✿✿。最后把Change Buffer记录到数据页的操作叫做merge✿✿。什么时候发生merge?有几种情况✿✿:在访问这个数据页的时候✿✿,或者用过访问后台线程内参揭幕✿✿、或者数据库shutdown✿✿、redolog写满 时候触发✿✿。
RedoLog 也不是每次都写入磁盘✿✿,在Buffer pool里面有一块内存区域(Log Buffer)专门用于保存 将要写入的内存文件的数据内参揭幕✿✿,默认是16m✿✿,它一样可以节省磁盘io✿✿。
需要注意✿✿:redo log的内容主要是用于崩溃数据的恢复✿✿。磁盘文件的数据文件✿✿,数据来自于buffer pool✿✿,redo log 写入磁盘✿✿,而不是写入文件✿✿。写入时间是参数配置的✿✿,默认是1
表空间可以看做是INNODB的存储引擎逻辑结构的最高层✿✿,所有的数据都存放在表空间中✿✿。INNODB的表空间分为五大块✿✿。
1.undo(不详)✿✿,也可以设置为单独表空间✿✿。2.数据字典✿✿:由内部表构成✿✿,存储表和索引的元数据(定义信息)✿✿。3.双写缓冲(INNODB的特性)✿✿。
在存储引擎写的过程如果宕机✿✿,可能出现页只写了一部分的情况(partial page write部分写失效)可能会导致数据丢失✿✿。
为什么需要双写缓冲?如果页崩溃之前它已经损坏了✿✿,那么用来做崩溃恢复没有任何意义✿✿。所以在运用redo log的时候需要一个页副本✿✿,如果出现部分写失效就用页的 副本还原页再完成崩溃恢复✿✿。这个页的副本就是double write✿✿,innodb的双写技术✿✿。
开启后✿✿,每个表都会开辟一个表空间✿✿,这个文件就是数据目录下的ibd文件✿✿,存放表的索引和数据✿✿。但是其他类的数据✿✿,如回滚(undo)信息✿✿,插入缓冲索引页✿✿、系统事务信息✿✿,双写缓冲还是放在原来的表空间✿✿。
也是 一种共享表空间✿✿,跟ibdate1类似✿✿。可以创建一个通用的表空间✿✿,用来存储不同数据库的表✿✿,数据路径文件和自己定义✿✿。
存储临时表的数据✿✿,包括用户创建的临时表✿✿,和磁盘的内部临时表✿✿,对应ibtmp1文件✿✿,当数据库服务关闭时候✿✿,该表空间删除✿✿,下次重新产生✿✿。
undo log的数据默认在系统表空间ibdata1文件中✿✿,因为共享表空间是不自动收缩的✿✿,也可以单独创建表空间✿✿。
DDL(data definition language)是数据定义语言✿✿:DDL比DML要多✿✿,主要的命令有CREATE✿✿、ALTER✿✿、DROP等✿✿,DDL主要是用在定义或改变表(TABLE)的结构✿✿,数据类型✿✿,表之间的链接和约束等初始化工作上✿✿,他们大多在建立表时使用✿✿。
DCL(DataControlLanguage)是数据库控制语言✿✿:是用来设置或更改数据库用户或角色权限的语句✿✿,包括(grant,deny,revoke等)语句✿✿。
binlog 以事件的形式记录所有的DDL和DML语句(因为它记录的是操作而不是数据值✿✿,属于逻辑日志)可以用来做主从复制和数据恢复✿✿。
开启了binlog功能的情况下✿✿,我们可以把binlog导出成SQL语句✿✿,把所有的操作重放一遍✿✿,来实现数据恢复✿✿。还有一种功能就是主从复制财经消息✿✿,✿✿,原理就是从服务器中读取主服务器的binlog✿✿,然后执行一遍✿✿。
执行:update user set name = dia where id = 1;1.先查到这条数据✿✿,如果有缓存则使用✿✿。2.把name值修改✿✿,然后调用引擎api接口✿✿,写入这条数据到内存中✿✿。这个时候redolog进入prepare状态✿✿,告诉执行器执行完成✿✿,可以提交✿✿。3.执行器收到后通知binlog✿✿,然后调用存储引擎接口提交✿✿,并这是redolog为commit状态✿✿。4.更新完成✿✿。
1.先记录到内存✿✿,再到文件✿✿。2.记录redo log两个状态两个阶段✿✿。3.存储引擎和server 记录不一样的日志✿✿。4.先记录redo再记录binlog内参揭幕✿✿。
在存储引擎写的过程如果宕机✿✿,可能出现页只写了一部分的情况(partial page write部分写失效)可能会导致数据丢失✿✿。
比如我们执行把name改为dia✿✿,如果写完了redo log✿✿,还没有写入binlog的时候mysql 重启了✿✿。redolog 可用于数据恢复✿✿,所以写入磁盘的dia✿✿,然后binlog没有这个逻辑日志✿✿,如果这个时候出现主从同步✿✿,就会出现数据不一致的情况✿✿。
所以在写两个日志的情况下✿✿,binlog就充当一个事务的协调者✿✿。通过innodb来执行prepare或者commit✿✿、rollback欧亿体育官网✿✿。如果 binlog写入失败就不会提交✿✿。