第 3 章 MySQL 存储引擎简介 mysql
前言 sql
MyISAM 存储引擎是 MySQL 默认的存储引擎,也是目前 MySQL 使用最为普遍的存储引擎之一。他的前身就是咱们在 MySQL 发展历程中所提到的 ISAM,是 ISAM 的升级版本。在 MySQL 最开始发行的时候是 ISAM 存储引擎,并且实际上在最初的时候,MySQL 甚至是没有存储引擎这个概念的。MySQL 在架构上面也没有像如今这样的 sql layer 和 storage engine layer 这两个结构清晰的层次结构,当时无论是代码自己仍是系统架构,对于开发者来讲都很痛苦的一件事情。到后来,MySQL 意识到须要更改架构,将前 端的业务逻辑和后端数据存储以清晰的层次结构拆分开的同时,对 ISAM 作了功能上面的扩展和代码的重构,这就是 MyISAM 存储引擎的由来。 数据库
MySQL 在 5.1(不包括)以前的版本中,存储引擎是须要在 MySQL 安装的时候就必须和 MySQL 一块儿被编译并同时被安装的。也就是说,5.1 以前的 版本中,虽然存储引擎层和 sql 层的耦合已经很是少了,基本上彻底是经过接口来实现交互,可是这两层之间仍然是没办法分离的,即便在安装的时候也是同样。 后端
可是从 MySQL5.1 开始,MySQL AB 对其结构体系作了较大的改造,并引入了一个新的概念:插件式存储引擎体系结构。MySQL AB 在架构改造的时候,让存储引擎层和 sql 层各自更为独立,耦合更小,甚至能够作到在线加载信的存储引擎,也就是彻底能够将一个新的存储引擎加载到一个正在 运行的 MySQL 中,而不影响 MySQL 的正常运行。插件式存储引擎的架构,为存储引擎的加载和移出更为灵活方便,也使自行开发存储引擎更为方便简单。在 这一点上面,目前尚未哪一个数据库管理系统可以作到。 安全
MySQL 的插件式存储引擎主要包括 MyISAM,Innodb,NDB Cluster,Maria,Falcon, Memory,Archive,Merge,Federated 等,其中最著名并且使用最为普遍的 MyISAM 和 Innodb 两种存储引擎。MyISAM 是 MySQL 最先的 ISAM 存储引擎的升级版本,也是 MySQL 默认的存储引擎。而 Innodb 实 际上并非 MySQ 公司的,而是第三方软件公司 Innobase(在 2005 年被 Oracle 公司所收购)所开发,其最大的特色是提供了事务控制等特性, 因此使用者也很是普遍。 服务器
其余的一些存储引擎相对来讲使用场景要稍微少一些,都是应用于某些特定的场景,如 NDB Cluster 虽然也支持事务,可是主要是用于分布式环境,属于一个 share nothing 的分布式数据库存储引擎。Maria 是 MySQL 最新开发(尚未发布最终的 GA 版本)的对 MyISAM 的升级版存储引擎,Falcon 是 MySQL 公司自行研发的为了替代当前的 Innodb 存储引擎的一款带有事务等高级特性的数据库存储引擎,目前正在研发阶段。Memory 存储引擎全部数 据和索引均存储于内存中,因此主要是用于一些临时表,或者对性能要求极高,可是容许在西噢他嗯 Crash 的时候丢失数据的特定场景下。Archive 是一 个数据通过高比例压缩存放的存储引擎,主要用于存放过时并且不多访问的历史信息,不支持索引。Merge 和 Federated 在严格意义上来讲,并不能算 做一个存储引擎。由于 Merge 存储引擎主要用于将几个基表 merge 到一块儿,对外做为一个表来提供服务,基表能够基于其余的几个存储引擎。而 Federated 实际上所作的事情,有点相似于 Oracle 的 dblink,主要用于远程存取其余 MySQL 服务器上面的数据。 数据结构
MyISAM 存储引擎的表在数据库中,每个表都被存放为三个以表名命名的物理文件。首先确定会有任何存储引擎都不可缺乏的存放表结构定义信息的.frm 文件,另外还有.MYD 和.MYI 文件,分别存放了表的数据(.MYD)和索引数据(.MYI)。每一个表都有且仅有这样三个文件作为 MyISAM 存储类型的表的存储,也就是说无论这个表有多少个索引,都是存放在同一个.MYI 文件中。 架构
MyISAM 支持如下三种类型的索引: 并发
一、B-Tree 索引 分布式
B-Tree 索引,顾名思义,就是全部的索引节点都按照 balance tree 的数据结构来存储,全部的索引数据节点都在叶节点。
二、R-Tree 索引
R-Tree 索引的存储方式和 b-tree 索引有一些区别,主要设计用于为存储空间和多
维数据的字段作索引,因此目前的 MySQL 版原本说,也仅支持 geometry 类型的字段做索引。
三、Full-text 索引
Full-text 索引就是咱们长说的全文索引,他的存储结构也是 b-tree。主要是为了解决在咱们须要用 like 查询的低效问题。
MyISAM 上面三种索引类型中,最常用的就是 B-Tree 索引了,偶尔会使用到 Fulltext,可是 R-Tree 索引通常系统中都是不多用到的。另外 MyISAM 的 B-Tree 索引有一个较大的限制,那就是参与一个索引的全部字段的长度之和不能超过 1000 字节。
虽然每个 MyISAM 的表都是存放在一个相同后缀名的.MYD 文件中,可是每一个文件的存放格式实际上可能并非彻底同样的,由于 MyISAM 的数据存放格式是分为静态(FIXED)固定长度、动态(DYNAMIC)可变长度以及压缩(COMPRESSED)这三种格式。固然三种格式中是否压缩是彻底能够任由咱们本身选择的,能够在建立表的时候经过 ROW_FORMAT 来指定 {COMPRESSED | DEFAULT},也能够经过 myisampack 工具来进行压缩,默认是不压缩的。而在非压缩的状况下,是静态仍是动态,就和咱们表中个字段的定义相关了。只要表中有可变长度类型的字段存在,那么该表就确定是 DYNAMIC 格式的,若是没有任何可变长度的字段,则为 FIXED 格式,固然,你也能够经过 alter table 命令,强行将一个带有 VARCHAR 类型字段的 DYNAMIC 的表转换为 FIXED,可是所带来的结果是原 VARCHAR 字段类型会被自动转换成 CHAR 类型。相反若是将 FIXED 转换为 DYNAMIC,也会将 CHAR 类型字段转换为 VARCHAR 类型,因此你们手工强行转换的操做必定要谨慎。
MyISAM 存储引擎的表是否足够可靠呢?在 MySQL 用户参考手册中列出在遇到以下状况的时候可能会出现表文件损坏:
MyISAM 存储引擎的某个表文件出错以后,仅影响到该表,而不会影响到其余表,更不会影响到其余的数据库。若是咱们的出据苦正在运行过程当中发现某个 MyISAM 表出现问题了,则能够在线经过 check table 命令来尝试校验他,并能够经过 repair table 命令来尝试修复。在数据库关闭状态下,咱们也能够经过 myisamchk 工具来对数据库中某个(或某些)表进行检测或者修复。不过强烈建议不到万不得已不要轻易对表进行修复操做,修复以前尽可能作好可能的备份工做,以避免带来没必要要的后果。
另外 MyISAM 存储引擎的表理论上是能够被多个数据库实例同时使用同时操做的,可是不管是咱们都不建议这样作,并且 MySQL 官方的用户手册中也有提到,建议尽可能不要在多个 mysqld 之间共享 MyISAM 存储文件。
在 MySQL 中使用最为普遍的除了 MyISAM 以外,就非 Innodb 莫属了。Innodb 作为第三方公司所开发的存储引擎,和 MySQL 遵照相同的开源 License 协议。
Innodb 之因此能如此受宠,主要是在于其功能方面的较多特色:
Innodb 在功能方面最重要的一点就是对事务安全的支持,这无疑是让 Innodb 成为 MySQL 最为流行的存储引擎之一的一个很是重要缘由。并且实现了 SQL92 标准所定义的全部四个级别(READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ 和 SERIALIZABLE)。对事务安全的支持,无疑让不少以前由于特殊业务要求而不得不放弃使用 MySQL 的用户转向支持
MySQL,以及以前对数据库选型持观望态度的用户,也大大增长了对 MySQL 好感。
Innodb 在事务支持的同时,为了保证数据的一致性已经并发时候的性能,经过对 undo 信息,实现了数据的多版本读取。
Innodb 改变了 MyISAM 的锁机制,实现了行锁。虽然 Innodb 的行锁机制的实现是经过索引来完成的,但毕竟在数据库中 99%的 SQL 语句都是要使用索引来作检索数据的。因此,行锁定机制也无疑为 Innodb 在承受高并发压力的环境下加强了不小的竞争力。
Innodb 实现了外键引用这一数据库的重要特性,使在数据库端控制部分数据的完整性成为可能。虽然不少数据库系统调优专家都建议不要这样作,可是对于很多用户来讲在数据库端加如外键控制可能仍然是成本最低的选择。
除了以上几个功能上面的亮点以外,Innodb 还有不少其余一些功能特点经常带给使用者不小的惊喜,同时也为 MySQL 带来了更多的客户。
在物理存储方卖弄,Innodb 存储引擎也和 MyISAM 不太同样,虽然也有.frm 文件来存放表结构定义相关的元数据,可是表数据和索引数据是存放在一块儿的。至因而每一个表单独存放仍是全部表存放在一块儿,彻底由用户来决定(经过特定配置),同时还支持符号连接。
Innodb 的物理结构分为两大部分: 一、数据文件(表数据和索引数据)
存放数据表中的数据和全部的索引数据,包括主键和其余普通索引。在 Innodb 中,存在了表空间(tablespace)这样一个概念,可是他和 Oracle 的表空间又有较大的不一样。首先,Innodb 的表空间分为两种形式。一种是共享表空间,也就是全部表和索引数据被存放在同一个表空间(一个或多个数据文件)中,经过 innodb_data_file_path 来指定,增长数据文件须要停机重启。 另一种是独享表空间,也就是每一个表的数据和索引被存放在一个单独的.ibd 文件中。
虽然咱们能够自行设定使用共享表空间仍是独享表空间来存放咱们的表,可是共享表空间都是必须存在的,由于 Innodb 的 undo 信息和其余一些元数据信息都是存放在共享表空间里面的。共享表空间的数据文件是能够设置为固定大小和可自动扩展大小两种形式的,自动扩展形式的文件能够设置文件的最大大小和每次扩展量。在建立自动扩展的数据文件的时候,建议你们最好加上最大尺寸的属性,一个缘由是文件系统自己是有必定大小限制的(可是 Innodb 并不知道),还有一个缘由就是自身维护的方便。另外,Innodb 不只可使用文件系统,还可使用原始块设备,也就是咱们常说的裸设备。
当咱们的文件表空间快要用完的时候,咱们必需要为其增长数据文件,固然,只有共享表 空 间 有 此 操 做 。 共 享 表 空 间 增 加 数 据 文 件 的 操 做 比 较 简 单 , 只 需 要 在 innodb_data_file_path 参数后面按照标准格式设置好文件路径和相关属性便可,不过这里有一点须要注意的,就是 Innodb 在建立新数据文件的时候是不会建立目录的,若是指定目录不存在,则会报错并没有法启动。另一个较为使人头疼的就是 Innodb 在给共享表空间增长数据文件以后,必需要重启数据库系统才能生效,若是是使用裸设备,还须要有两次重启 。
这也是我一直不太喜欢使用共享表空间而选用独享表空间的缘由之一。
二、日志文件
Innodb 的日志文件和 Oracle 的 redo 日志比较相似,一样能够设置多个日志组(最少 2 个),一样采用轮循策略来顺序的写入,甚至在老版本中还有和 Oracle 同样的日志归档特性 。若是你的数据库中有建立了 Innodb 的表,那么千万别所有删除 innodb 的日志文件,由于极可能就会让你的数据库 crash,没法启动,或者是丢失数据。
因为 Innodb 是事务安全的存储引擎,因此系统 Crash 对他来讲并不能形成很是严重的损失,因为有 redo 日志的存在,有 checkpoint 机制的保护,Innodb 彻底能够经过 redo 日志将数据库 Crash 时刻已经完成但尚未来得及将数据写入磁盘的事务恢复,也可以将全部部分完成并已经写入磁盘的未完成事务回滚并将数据还原。
Innodb 不只在功能特性方面和 MyISAM 存储引擎有较大区别,在配置上面也是单独处理的。在 MySQL 启动参数文件设置中,Innodb 的全部参数基本上都带有前缀"innodb_",不管是 innodb 数据和日志相关,仍是其余一些性能,事务等等相关的参数都是同样。和全部 Innodb 相关的系统变量同样,全部的 Innodb 相关的系统状态值也一样所有以"Innodb_" 前缀。固然,咱们也彻底能够仅仅经过一个参数(skip-innodb)来屏蔽 MySQL 中的 Innodb 存储引擎,这样即便咱们在安装编译的时候将 Innodb 存储引擎安装进去了,使用者也没法建立 Innodb 的表。
NDB 存储引擎也叫 NDB Cluster 存储引擎,主要用于 MySQL Cluster 分布式集群环境,
Cluster 是 MySQL 从 5.0 版本才开始提供的新功能。这部分咱们可能并不只仅只是介绍 NDB 存储引擎,由于离开了 MySQL CLuster 整个环境,NDB 存储引擎也将失去太多意义。 因此这一节主要是介绍一下 MySQL Cluster 的相关内容。
简单的说,Mysql Cluster 实际上就是在无共享存储设备的状况下实现的一种内存数据库 Cluster 环境,其主要是经过 NDB Cluster(简称 NDB)存储引擎来实现的。
通常来讲,一个 Mysql Cluster 的环境主要由如下三部分组成: a) 负责管理各个节点的 Manage 节点主机:
管理节点负责整个 Cluster 集群中各个节点的管理工做,包括集群的配置,启动关闭各节点,以及实施数据的备份恢复等。管理节点会获取整个 Cluster 环境中各节点的状态和错误信息,而且将各 Cluster 集群中各个节点的信息反馈给整个集群中其余的全部节点。因为管理节点上保存在整个 Cluster 环境的配置,同时担任了集群中各节点的基本沟通工做,因此他必须是最早被启动的节点。
NDB 是一个内存式存储引擎也就是说,他会将全部的数据和索引数据都 load 到内存中 ,但也会将数据持久化到存储设备上。不过,最新版本,已经支持用户本身选择数据能够不所有 Load 到内存中了,这对于有些数据量太大或者基于成本考虑而没有足够内存空间来存放全部数据的用户来讲的确是一个大好消息。
NDB 节点主要是实现底层数据存储的功能,保存 Cluster 的数据。每个 NDB 节点保存完整数据的一部分(或者一份完整的数据,视节点数目和配置而定),在 MySQL CLuster 里面叫作一个 fragment。而每个 fragment,正常状况来说都会在其余的主机上面有一份(或者多分)彻底相同的镜像存在。这些都是经过配置来完成的,因此只要配置得当,Mysql Cluster 在存储层不会出现单点的问题。通常来讲,NDB 节点被组织成一个一个的 NDB Group,一个 NDB Group 实际上就是一组存有彻底相同的物理数据的 NDB 节点群。
上面提到了 NDB 各个节点对数据的组织,可能每一个节点都存有所有的数据也可能只保存一部分数据,主要是受节点数目和参数来控制的。首先在 Mysql Cluster 主配置文件(在管理节点上面,通常为 config.ini)中,有一个很是重要的参数叫 NoOfReplicas,这个参数指定了每一份数据被冗余存储在不一样节点上面的份数,该参数通常至少应该被设置成 2,也只须要设置成 2 就能够了。由于正常来讲,两个互为冗余的节点同时出现故障的几率仍是很是小的,固然若是机器和内存足够多的话,也能够继续增大。一个节点上面是保存全部的数据仍是一部分数据,还受到存储节点数目的限制。NDB 存储引擎首先保证 NoOfReplicas 参数配置的要求对数据冗余,来使用存储节点,而后再根据节点数目将数据分段来继续使用多余的 NDB 节点,分段的数目为节点总数除以 NoOfReplicas 所得。
MySQL Cluster 自己所包含的内容很是之多,出于篇幅考虑,这里暂时不作很深刻的介绍,在本书的架构设计部分的高可用性设计一章中将会有更为详细的介绍与实施细节,你们也能够经过 MySQL 官方文档来进一步了解部分细节。
MERGE 存储引擎,在 MySQL 用户手册中也提到了,也被你们认识为 MRG_MyISAM 引擎。
Why?由于 MERGE 存储引擎能够简单的理解为其功能就是实现了对结构相同的 MyISAM 表 ,经过一些特殊的包装对外提供一个单一的访问入口,以达到减少应用的复杂度的目的。要建立
MERGE 表,不只仅基表的结构要彻底一致,包括字段的顺序,基表的索引也必须彻底一致。
MERGE 表自己并不存储数据,仅仅只是为多个基表提供一个赞成的存储入口。因此在建立 MERGE 表的时候,MySQL 只会生成两个较小的文件,一个是.frm 的结构定义文件,还有一
个.MRG 文件,用于存放参与 MERGE 的表的名称(包括所属数据库 schema)。之因此须要有所属数据库的 schema,是由于 MERGE 表不只能够实现将 Merge 同一个数据库中的表,还能够
Merge 不一样数据库中的表,只要是权限容许,而且在同一个 mysqld 下面,就能够进行 Merge。
MERGE 表在被建立以后,仍然能够经过相关命令来更改底层的基表。
MERGE 表不只能够提供读取服务,也能够提供写入服务。要让 MERGE 表提供可 INSERT 服务,必须在在表被建立的时候就指明 INSERT 数据要被写入哪个基表,能够经过 insert_method 参数来控制。若是没有指定该参数,任未尝试往 MERGE 表中 INSERT 数据的操做,都会出错。此外,没法经过 MERGE 表直接使用基表上面的全文索引,要使用全文索引 ,必须经过基表自己的存取才能实现。
Memory 存储引擎,经过名字就很容易让人知道,他是一个将数据存储在内存中的存储引擎。Memory 存储引擎不会将任何数据存放到磁盘上,仅仅存放了一个表结构相关信息的.frm 文件在磁盘上面。因此一旦 MySQL Crash 或者主机 Crash 以后,Memory 的表就只剩下一个结构了。Memory 表支持索引,而且同时支持 Hash 和 B-Tree 两种格式的索引。因为是存放在内存中,因此 Memory 都是按照定长的空间来存储数据的,并且不支持 BLOB 和 TEXT 类型的字段。Memory 存储引擎实现页级锁定。
既然全部数据都存放在内存中,那么他对内存的消耗量是可想而知的。在 MySQL 的用户手册上面有这样一个公式来计算 Memory 表实际须要消耗的内存大小:
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
BDB 存储引擎全称为 BerkeleyDB 存储引擎,和 Innodb 同样,也不是 MySQL 本身开发实现的一个存储引擎,而是由 Sleepycat Software 所提供,固然,也是开源存储引擎,一样支持事务安全。
BDB 存储引擎的数据存放也是每一个表两个物理文件,一个.frm 和一个.db 的文件,数据和索引信息都是存放在.db 文件中。此外,BDB 为了实现事务安全,也有本身的 redo 日 志 ,和 Innodb 同样,也能够经过参数指定日志文件存放的位置。在锁定机制方面,BDB 和 Memory 存储引擎同样,实现页级锁定。
因为 BDB 存储引擎实现了事务安全,那么他确定也须要有本身的 check point 机 制 。BDB 在每次启动的时候,都会作一次 check point,而且将以前的全部 redo 日志清空。在运行过程当中,咱们也能够经过执行 flush logs 来手工对 BDB 进行 check point 操做。
FEDERATED 存储引擎所实现的功能,和 Oracle 的 DBLINK 基本类似,主要用来提供对远程 MySQL 服务器上面的数据的访问借口。若是咱们使用源码编译来安装 MySQL,那么必须手工指定启用
FEDERATED 存储引擎才行,由于 MySQL 默认是不起用该存储引擎的。
当咱们建立一个 FEDERATED 表的时候,仅仅在本地建立了一个表的结构定义信息的文件而已,全部数据均实时取自远程的 MySQL 服务器上面的数据库。
当咱们经过 SQL 操做 FEDERATED 表的时候,实现过程基本以下: a、SQL 调用被本地发布 b、MySQL 处理器 API(数据以处理器格式) c、MySQL 客户端 API(数据被转换成 SQL 调用)
ARCHIVE 存储引擎主要用于经过较小的存储空间来存放过时的不多访问的历史数据。 ARCHIVE 表不支持索引,经过一个.frm 的结构定义文件,一个.ARZ 的数据压缩文件还有一个.ARM 的 meta 信息文件。因为其所存放的数据的特殊性,ARCHIVE 表不支持删除,修改操做,仅支持插入和查询操做。锁定机制为行级锁定。
BLACKHOLE 存储引擎是一个很是有意思的存储引擎,功能恰如其名,就是一个"黑洞"。就像咱们 unix 系统下面的"/dev/null"设备同样,无论咱们写入任何信息,都是有去无回 。那么 BLACKHOLE 存储引擎对咱们有什么用呢?在我最初接触 MySQL 的时候我也有过一样的疑问,不知道 MySQL 提供这样一个存储引擎给咱们的用意为什么?可是后来在又一次数据的迁移过程当中,正是 BLACKHOLE 给我带来了很是大的功效。在那次数据迁移过程当中,因为数据须要通过一个中转的 MySQL 服务器作一些相关的转换操做,而后再经过复制移植到新的服务器上面。可当时我没有足够的空间来支持这个中转服务器的运做。这时候就显示出 BLACKHOLE 的功效了,他不会记录下任何数据,可是会在 binlog 中记录下全部的 sql。而这些 sql 最终都是会被复制所利用,并实施到最终的 slave 端。
MySQL 的用户手册上面还介绍了 BLACKHOLE 存储引擎其余几个用途以下: a、SQL 文件语法的验证。
CSV 存储引擎实际上操做的就是一个标准的 CSV 文件,他不支持索引。起主要用途就是你们有些时候可能会须要经过数据库中的数据导出成一份报表文件,而 CSV 文件是不少软件都支持的一种较为标准的格式,因此咱们能够经过先在数据库中创建一张 CVS 表,而后将生成的报表信息插入到该表,便可获得一份 CSV 报表文件了。
多存储引擎是 MySQL 有别于其余数据库管理软件的最大特点,不一样的存储引擎有不一样的特色,能够应对不一样的应用场景,这让咱们在实际的应用中能够根据不一样的应用特色来选择最有利的存储引擎,给了咱们足够的灵活性。经过这一章对 MySQL 各个存储引擎的初步了解,我想各位读者朋友应该已经对 MySQL 的主要存储引擎有了必定的认识,在后续的章节中对于一些经常使用的存储引擎还会有更为深刻的介绍。