一 . 前言

总是看到有说MySQL某个数据引擎哪里哪里有问题的 , 让我一度怀疑我是不是Mysql 用的不对 ,有些问题都没有遇到过,所以我非常好奇 , 数据库的存储引擎 , 大家真的在用吗?

MySQL 官方文档:: MySQL 5.7 Reference Manual :: 15 Alternative Storage Engines

二. 涉及的引擎

2.1 不同存储引擎的特性

修改引擎的相关命令

// 查看 MySQL 版本 (不同版本对于存储引擎的支持不一样) SELECT VERSION(); // 查看支持的引擎 show engines; // 修改引擎类型 alter table table_name engine=innodb; 复制代码

三. 引擎的选择

了解存储引擎的区别只是一方面 , 更重要的是在何种场景下应该选择哪些存储引擎. 存储引擎使用最多的应该是四种 : InnoDB , MyISAM , Archive , Memory .

但是实际上真正可能用的多的 , 只会是 InnoDB 和 MyISAM

3.1 引擎的选择

MySQL 各个存储引擎的使用空间可以说越来越小了, 比如 Memory , 锁是表锁 , 又不能持久化数据. 也许业务场景中唯一的作用就是节约成本 , 不用搭一套Redis .

但是都上云了 , MySQL 服务器内存的开销 , 相对价格也不会便宜到哪去.

而针对于 csv 引擎 , 其实就是存储CSV文件, 那么搞一套OSS系统存这些可能更便宜.

而更有价值的可能就是各种图引擎或者特殊功能的引擎 , 但是往往都会有更好的替代品.

对于这些引擎总结起来就一句话 : 除非需要用到某些InnoDB 不具备的特性,并且没有其他办 怯可以替代,否则都应该优先选择Inno DB 引擎

那么剩下的 , 就是 InnoDB 和 MylSAM 了~~~

3.2 InnoDB 和 MylSAM 的选择

MySQL 的引擎太多了, 用的最多的应该就是 InnoDB 和 MylSAM, 这也是涉及篇幅最大的两个数据引擎.

两个存储引擎的区别很多 , 但是正在的核心集中在以下几个方面 :

是否支持事务

MyISAM 本身是不支持事务的 ,

事务就很重要了 , 如果业务线比较长 ,而且强制要求数据完整一致. InnoDB.

如果本身就是单次操作或者可以通过 TCC 的方式进行回滚 , 那么选择 MyISAM 也不会对业务产生什么影响.

MVCC

MyISAM 是不支持 MVCC 的 , MVCC 是 多版本并发控制 , 如果对事务接触比较深 , 就会了解到四种隔离级别. 而 MySQL 的事务隔离级别就是基于 MVCC 进行实现.

外键

外键通常用来保证数据的完整性 ,A表的字段是B表的主键,就可以为该字段设置外键约束。 InnoDB 支持外键而 MyISAM 不支持.

外键其实很讨厌 , 删除数据时如果有外键关联 , 会导致数据删除不掉,处理起来也会非常复杂. 同时由于强调多表关联 , 也会导致性能较差

但是外键好处也很强大 , 保证了数据的一致和完整. 再也不怕用户未删除 ,而属性被删除的问题.

不过个人接触的几个系统里面就一个使用了外键 ,所以这个特性不能影响到引擎的选择~~

锁粒度

锁粒度通常是指行锁和表锁. InnoDB 锁粒度为行锁 ,而 MyISAM 为表锁.

行锁和表锁不能一概而论 :

  • 表锁面积更大 , 但是申请锁只需要进行一次 ,单次锁的处理时间更短

  • 行锁面积小 , 但是需要申请多次锁 , 单次处理的时间更长

四 . 引擎的对比

了解理论还是不够 , 所以期望能从数据上看一看 , 两个存储引擎到底差了多少 . 实际业务中有没有必要使用特殊的引擎建表

4.1 InnoDB 与 MylSAM 的性能差距

MyISAM 更快的原因

// 索引不同 : - MyISAM 只有三个文件:索引文件,表结构文件,数据文件 - InnerDB 基于 BTree 的索引方法 > 宏观 : MyISAM 直接加载索引文件到内存中,由于索引文件的数据量更少,相同时间加载的索引数据就更多 > 微观 :InnerDB 寻址需要查询到块,再在块中找到对应的行,但是MyISAM查询数据很快,直接标识的OFFSET地址 // 事务 : - InnerDB 处理时需要维护事务,越复杂的场景这种损耗就会越高 // 缓存机制的不同 : - MyISAM 使用 KeyCache ,将频繁访问的索引块直接放到内存中 - InnerDB 使用 BufferPool ,会缓存数据和索引 > 相对而言MyISAM能够缓存的数据更多,实际操作也能发现,第二次查询InnerDB需要 10 秒,而MyISAM只用 1 秒 复制代码

4.2 理解事务

上面列举了一堆事务和性能什么什么的,但是不论用什么引擎,都需要深入了解性能和事务的直接联系。

首先事务的原理是什么 , 从单机事务的角度来说 ,事务主要是基于MySQL来实现 ,简单来说就是从 START TRANSACTION 来开启事务 ,到 COMMIT 结束事务 。

而看似简单的两个步骤 ,整个在InnerDB中的执行过程是很长的。

以 InnerDB 为例 , 该引擎为事务提供了四种隔离级别 : 读未提交 , 读已提交 , 可重复读 , 可串行化。 为了实现这四种隔离级别 ,InnerDB 对数据进行了加锁 , MVCC , lock in share mode 等操作 。

就光加锁这一项,就限制了并发的能力。而MVCC机制带来的快照,同样会对性能有所影响。其他的引擎同理

// PS : 性能指标是绝对的吗? (100万数据) - READ_UNCOMMITTED : 读未提交 >> 58 秒 - READ_COMMITTED : 读已提交 >> 55 秒 - REPEATABLE_READ : 可重复读 >> 35 秒 复制代码

很奇怪不是 , 为什么我们看到的越严格的隔离级别反而少了时间 :

  • 因为性能和锁挂钩 ,而锁往往只会在复杂的业务场景中才会有冲突,才会存在并发的问题,我这里就是单纯的写,本身并不会出现什么锁的竞争,也就没什么事务的问题。

4.3 理解外键

InnerDB 的外键这东西,用好了妥妥的可靠性小助手,再也不怕某个数据不存在而作一堆查询和判断。数据的完备性大大的提升。

但是这功能没用好,简直能把人恶心死。外键的设计,是需要对系统有很深的理解的,哪些数据应该绑定,哪些数据不应该建立耦合关系很重要。

但是现在的系统设计思路,会考虑逻辑删除数据,这个时候外键的作用就很小了。

而外键同样是会对性能带来损耗的 :

外键的目的在于绑定多张表之间的关系,外键在进行子表的写入操作时,是会对主表加共享锁,而一旦加了锁,在并发的场景下,就会有性能的问题。

综合考虑下 : 外键的功能仅适用于特殊场景下的完整性约束,而在并发的需求下,能不用就不用吧

总结

本着学习的目的了解了这些 , 虽然MySQL 本身还支持很多种其他的引擎 , 但是最好还是不要尝鲜. 用的时候一时爽 , 回头上云或者切库的时候 , 那怕是后悔的不得了.

一般业务里面其实基本上都会选用 InnoDB , 极个别场景会选用 MyISAM, 其实其他的引擎都可以用外部组件来解决. Redis ,MongoDB , ES 就是用来解决这些问题的 , 所以已经没有什么理由非要用 MyISAM 了,而其他的引擎,基本上不需要在生产上实践

而伴随着分库分表的流行 , 加上很多公司会选择把大数据的计算交给大数据部门来处理, 对 MySQL 的压力是在逐步变小的.

另外需要注意 , 性能这东西并不是绝对的,这篇文章不好实践,也不好追代码,都是看看别人的博客,然后理解吸收后用自己的话表述出来,也不知道是不是真的~~~

看看实践者的文章 》》

-# MyISAM和InnoDB批量插入1万数据速度比较

附录 : 各种存储引擎

InnoDB :

  • InnoDB 的数据存储在表空间( tablespace )中

  • InnoDB 采用MVCC 来支持高井发,并且实现了四个标准的隔离级别

  • InnoDB 表是基于聚簇索引建立的

MylSAM

  • MyISAM 提供了全文索引、压缩、空间函数( GIS ) 等,但My ISAM 不支持事务和行级

  • MyISAM 会将表存储在两个文件中: 数据文件和索引文件,分别以.MYD 和. MYI 为扩展名

  • MyISAM 表可以包含动态或者静态(长度固定)行。

  • 可以使用myisa 1叩a c k 对My ISAM 表进行压缩(也叫打包pack ), 压缩表是不能进行修 改的

Archive 引擎

  • Archive 存储引擎只支持INSERT 和SELECT 操作 , Archive 引擎会缓存所有的写并利用zlib 对插入的行进行压缩 , 磁盘 IO 更少

  • 表适合日志和数据采集类应用

  • 支持行级锁和专用的缓冲区,所以可以实现高并发的插入

Blackhole 引擎 (问题太多 , 不推荐)

  • 会丢弃所有插入的数据,不做任何保存。但是服务器会记录Blackhole 表的日志,所以可以用于复制数据到备库,或者只是简单地记录到日志

  • 在一些特殊的复制架构和日志审核时发挥作用。

csv 引擎

  • 将普通的csv 文件(逗号分割值的文件)作为MySQL 的表来处理

  • 不支持索引。csv 引擎可以在数据库运行时拷入或者拷出文件

  • 将 Excel 等电子表格软件中的数据存储为csv 文件,然后复制到MySQL 数据目录下

Federated 引擎

  • 代理引擎 : 会创建一个到远程MySQL 服务器的客户端连接,井将查询传输到远程服务器执行,然后提取或者发送需要的数据。

Memory 引擎

  • 如果需要快速地访问数据,并且这些数据不会被修改,重启以后丢失也没有关系,那么使用Memory 表

  • Memory 表至少比MyISAM 表要快一个数量级

  • Memroy 表是表级锁,因此并发写入的性能较差

  • 每行长度固定 , 部分内存的搜费

Merge 引擎

  • Merge 表是由多个My ISAM 表合并而来的虚拟表

  • 可以用于将MySQL 用于日志或者数据仓库类应用