详细介绍了MySQL 的InnoDB和MyISAM存储引擎的区别。
存储引擎主要负责数据的存储和提取。其架构模式是插件式的,包括InnoDB、MyISAM、Memory 等多个可选的存储引擎,InnoDB 在5.5.5后成为默认存储引擎。存储引擎通过API与上层进行通信,这些API屏蔽了不同存储引擎之间的差异,使得这些差异对上层查询过程透明。MySQL的存储引擎架构将查询处理以及其他任务系统和数据的存储处理分离开来,这样做的好处在于可以根据需要灵活选择存储引擎,使得MySQL的架构具备很大的灵活性。
MySQL 5.5 之前,MyISAM 引擎是 MySQL 的默认存储引擎。MySQL 5.5版本引入InnoDB事务性数据库引擎,MySQL 5.5 版本及其之后默认的存储引擎为 InnoDB。
Mysql的InnoDB和MyISAM存储引擎的常见区别如下:
- 锁支持:MyISAM 只有表级锁(table-level locking),读取时加共享表锁,写入时加排它表锁,MyISAM 一锁就是锁住了整张表,在并发写的时候InnoDB性能远超MyISAM。而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁,行锁大幅度提高了多用户并发操作的新能,但行锁,只是在使用了索引时是有效的,如果没使用索引则会锁全表。
- 事务支持: MyISAM 不提供事务支持,InnoDB 提供事务支持,具有提交(commit)和回滚(rollback)事务的能力,这一点保证数据的正确性和完整性非常重要。
- MySQL InnoDB 引擎使用 redo log(重做日志) 保证事务的持久性,使用 undo log(回滚日志) 来保证事务的原子性。
- MySQL InnoDB 引擎通过 锁机制、MVCC 等手段来保证事务的隔离性( 默认支持的隔离级别是 REPEATABLE-READ )。
- 保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。
- 外键支持:MyISAM 不支持,而 InnoDB 支持。但是一般不在数据库使用外键,而是在应用层解决,使用外键会造成级联更新,且级联更新是强阻塞,存在数据库更新风暴的风险;外键用时也会影响数据库的插入速度。
- 主键支持:MyISAM允许没有主键的表存在。InnoDB表必须有主键,如果没有设定主键,就会自动生成一个 6 字节隐藏列作为主键列(用户不可见)。
- 数据库崩溃恢复的支持:MyISAM 不支持,而 InnoDB 支持。使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log、undo log、bin log。
- MVCC的支持:MyISAM 不支持,而 InnoDB 支持。MVCC 可以看作是行级锁的一个升级,可以有效减少加锁操作,提供性能。
- 主键自增记录:主键自增时只会比较最大自增主键值。MyISAM 表会把自增主键的最大ID记录到表数据文件里,重启MySQL 自增主键的最大ID也不会丢失。InnoDB 表只是把自增主键的最大 ID 记录到内存中,所以重启数据库会导致最大 ID 丢失,会以表中实际存在的最大主键为准。
- 实际上MySQL自增主键不能持久化算是一个臭名昭著的bug:https://bugs.mysql.com/bug.php?id=199。所以在Mysql 8.0后,InnoDB会把自增主键计数器的最新值写入redo log日志中,即使Mysql数据库发生重启,InnoDB也会根据redo log中的计数器信息来初始化其内存值,再也不怕自增主键丢失了。
- 索引结构:MyISAM使用非聚集索引,索引和数据分开,只缓存索引;InnoDB使用聚集索引,主索引和数据存在一个文件。
- 行数记录:InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快,但前提是没有任何WHERE条件,如果有条件,则此时都会去实际地去计算表的行数;
参考资料:
- 《 MySQL 技术内幕: InnoDB 存储引擎》
- 《高性能 MySQL》
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!