一 . 前言
总是看到有说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 引擎 <高性能MySQL>
那么剩下的 , 就是 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 的压力是在逐步变小的.
另外需要注意 , 性能这东西并不是绝对的,这篇文章不好实践,也不好追代码,都是看看别人的博客,然后理解吸收后用自己的话表述出来,也不知道是不是真的~~~
看看实践者的文章 》》
附录 : 各种存储引擎
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 用于日志或者数据仓库类应用