作者通过个人的学习过程和理解,感觉出,单一的去理解MySQL的存储引擎的概念或者理论是毫无意义的,本文章是引导性的一点一点引出存储引擎的理解,所以或许你最后还是没有理解存储引擎,但是你可能学到了一种学习方法。
首先,了解这样一个事实:MySQL最重要,最与众不同的特性就是他的存储引擎架构,这种架构的设计将查询处理及其他系统任务和数据的存储/提取相分离。(参考《高性能MySQL》一书)
那这句话怎么去理解呢?或者说,所谓的分离是怎么样的一种逻辑?
我们不妨先这样理解:MySQL就相当于一个大的框架,而这个框架其实就是其所谓的分离出的逻辑架构!
而这个逻辑架构可以简单理解为:一种层次关系!可以理解为这样的三层:
1.最上层的,也就是与客户端的连接管理的那层架构:并不是MySQL所特有的,比如连接处理,授权认证!
2.第二层架构,我们可以理解为服务层,也就是说大多数的mySQL的核心服务功能都在这一层,包括SQL解析,优化,缓存等!
3.第三层架构,也就是我们的存储引擎,它负责MySQL中数据的存储和提取。
以上内容,都是来自《高性能MySQL》一书,阐述上述内容主要是为了,有个基础的认知!
然后,我们来简单理解一下这些内容:
我们知道,数据库本身就是一个存数据的东西,通俗来说,一个TXT文本文件也可以存数据,当他存储数据的时候,我们就可以说这个TXT文本文件就是一个数据库。那么MySQL是什么?MySQL就是一个存储数据的服务器。只不过,他多出来了内置的各种处理操作,以便更好的管理所保存的数据。什么意思?如果你用txt文本文件去存储一些学生信息的数据,当你要查询一个名字为张三的学生信息的时候,你就必须自己手动的在这个文本文件中去找到这个学生的信息。而数据库服务器就是做出了这样的功能性的管理,你可以使用简单的查询语句就能够得到张三学生的信息!
所以,通俗直白的说,所谓的数据库就是一个存数据的东西,这个东西可以是任何可以存储东西的介质。而数据库服务器,则是在存储数据的基础上,增添了一系列基于数据的服务功能。
那么,此时你就应该理解了,MySQL就是一个数据库服务器,他可以存储数据,并提供一系列服务功能!
我们抛开上述的三层框架中的连接不看,把目光放在第二层和第三层,可以理解为这两层共同构成了数据库服务器实现其服务功能的逻辑组件。
那么,问题来了,这两层逻辑究竟是什么?
Server层:主要包括查询缓存、分析器、优化器、执行器等
存储引擎:主要负责数据的存储和读取
我们先来理解一条sql语句在服务器中的执行流程:当我们客服端与数据库服务器建立其相应的连接之后,执行一条sql语句,会先
查询缓存
Mysql会先校验这个sql是否执行过,以Key-Value的形式缓存在内存中,Key是查询预计,Value是结果集。如果缓存key被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。
Mysql 查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。
分析器
mysql 没有命中缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干嘛的:第一步,词法分析,一条SQL语句有多个字符串组成,首先要提取关键字,比如select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。第二步,语法分析,主要就是判断你输入的sql是否正确,是否符合mysql的语法。
优化器
优化器的作用就是它认为的最优的执行方案去执行(虽然有时候也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。
执行器
当选择了执行方案后,mysql就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。
看到这里,上述都只是简单的概括了Server层所提供的功能服务,此时我们如果你认真读了,你会看到,在执行器准备执行sql语句的时候,是去调用存储引擎的接口,然后返回执行结果。
好了,如果你对接口这个词语足够敏感,你会马上有这样一个想法,接口抽象出一套处理逻辑规范,然后具体的实现类去完成其所实现的方式。其实,某一特定的存储引擎,就是这个抽象接口下的具体实现者。
也就是说,服务器层通过API与存储引擎进行通信,这些接口屏蔽了不同存储引擎之间的差异,而只关心具体的实现者-也就是具体的某一个存储引擎,而存储引擎也只是去响应上层的请求。
存储引擎
存储引擎是数据库底层软件组织,数据库管理系统(也就是所谓的数据库服务器)用引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。
其实这时候的理解已经出来了,MySQL最核心的就是存储引擎,而存储引擎的作用抽象来说就是对底层数据的实际操作的管理者,包括存储和提取。比如特定的某一存储引擎决定了数据怎样存储,存储在哪?
MySQL中常用的存储引擎:
上述,我们已经知道了,某一具体的存储引擎有自己对底层数据进行操作的机制,也就是所谓的对于处理接口的具体实现。
首先,我们来查看一下,我们MySQL数据库中的存储引擎:
test是数据库名,student是表名;
上述语句都可以显示表的信息,其中包括了使用的是哪一个具体的存储引擎:
可以看到,此student表使用的Engine是InnoDB;
那我们怎么设置呢?
首先我们建表的时候可以指定:例如
我们来查看一下:
然后我们也可以不再创建的时候指定(这时候由服务器决定其默认的存储引擎),在任何时候使用修改语句指定:
再来查看一下:
好了,上述过程中出现了两个具体的存储引擎,InnoDB和MyISAM
我们来对比一下,这两个存储引擎:
InnoDB
首先,要了解的是,MySQL在其5.5版本之后,已经把InnoDB作为了其默认的存储引擎。
1.InnoDB是事务型的存储引擎,为表提供了事务(ACID)支持。
2.InnoDB具有事务提交,回滚,自动崩溃恢复的安全特性。
3.InnoDB采用多版本并发控制(MVCC)支持高并发并且实现了四个标准的隔离级别。
其默认的隔离级别为可重复读。
4.InnoDB支持行锁,只不过是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。
4.InnoDB支持外键。
5.InnoDB具有处理巨大数据量的最大性能设计,
CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的
6.InnoDB不支持全文索引
MyISAM
1.MyISAM不支持事务。
2.MyISAM不支持外键。
3.MyISAM不支持崩溃后的自动恢复。
4.MyISAM不支持行锁,支持表锁,所以其锁粒度较大。
那么MyISAM是不是一无是处呢?我们来看一下其特性:
1.MyISAM对整张表加锁,读取时会对需要读到的所有表加共享锁
写入时则对表加排他锁。但是在表有读取查询的同时,也可以往
表中插入新的记录(被称为并发插入)
2.MyISAM支持压缩表。
但是压缩表有个前提,就是该表不会再进行任何修改操作。
3.MyISAM有其索引特性。
即使是BLOB和TEXT等长字段,也可以基于其前500个字符创建索引。
4.MyISAM支持全文索引。
5.MyISAM拥有较高的插入、查询速度。
以上只是概括性的总结了常见两种存储引擎的特性和差别,具体的细节远不止这些,学习无止境。
那此时就有另一个问题,我们应该怎样来选择存储引擎呢?
存储引擎的选择
首先,明白这两个事实:
1.MySQL服务器5.5版本后设置其InnoDB为其默认存储引擎,当然你可以更改。
2.一个数据库中多个表可以使用不同引擎以满足各种性能和实际需求。
借用《高性能MySQL》一书中前辈的介绍:
1.大部分情况下,InnoDB都是正确的选择,所以MySQL5.5版本时终于将InnoDB作为默认的存储引擎了。
2.一句话总结:除非用到某些InnoDB不具备的特性,并且没有其他办法可以代替,否则都应该选择InnoDB引擎。
3.除非万不得已,否则建议不要混合使用多种存储引擎,尽管“数据库中的多个表可以根据性能和实际需求来选择不同的存储引擎"这句话看起来好像很合理,更人性化。但是,这其中可能隐藏了很多复杂的问题,以及一些潜在的bug和边界问题。
本身的存储引擎层和Server层的交互已经比较复杂,更不要说混合使用多个存储引擎了。
4.如果真的需要了多个存储引擎,则应考虑:事务,备份,崩溃恢复,特有的特性。
本文章到这里也要结束了,这也记录了个人在学习MySQL数据库存储引擎时候的成长历程。我也更希望,所有正在努力,正在学习的同学,能够掌握的是一种方法,一种系统的逻辑,而不是仅仅局限于某一特定的抽象概念。付出一定会有回报,如果你还没有感觉到回报,那就是付出的不够,加油!