MySQL存储引擎

概述

MySQL支持多种存储引擎,可以通过SHOW ENGINES命令查看MySQL所支持的所有存储引擎。

MySQL 当前默认的存储引擎是 InnoDB。并且,所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务

MySQL 5.5.5 之前MyISAM 是 MySQL 的默认存储引擎。5.5.5 版本之后,InnoDB 是 MySQL 的默认存储引擎。


MySQL存储引擎架构

MySQL存储引擎采用的是插件式架构,支持多种存储引擎。存储引擎是基于表的,不是基于数据库的


MyISAM和InnoDB有什么区别

MySQL 5.5之前,MyISAM引擎是默认存储引擎,但是MyISAM不支持事务和行级锁,且崩溃后无法安全恢复

InnoDB MyISAM
行级 支持 只有表级锁,在并发写的情况下,性能极差
事务 支持(默认使用可重读隔离级别,可以解决幻读问题的发生) 不支持
外键 支持(外键对于维护数据一致性非常有帮助,但是对性能有一定的损耗,因此通常情况下,不建议在实际生产项目中使用外键,而在业务代码中进行约束 不支持
安全恢复 支持(数据库在异常崩溃后,**重启时会保证数据库恢复到崩溃前的状态,这个过程依赖于redo log**) 不支持
索引实现 使用B+树作为索引结构,数据文件本身就是索引文件 使用B+树,索引文件和数据文件分离。
性能 随着CPU核数的增加,InnoDB的读写能力呈线性增长。 读写不能并发,所以处理能力和CPU核数无关。

InnoDB存储引擎对MVCC的实现

MVCC, Multi-Version Concurrency Control 多版本并发控制。MVCC是一种用于多个并发事务同时读写数据库时,保持数据的一致性和隔离性的机制。它通过undo log在每个数据行上维护多个版本的数据来实现。当一个事务要对数据库中的数据进行修改时,MVCC会为该事务创建一个数据快照,而不是直接修改实际的数据行

MVCC只在已提交读RC可重复读RR两个隔离级别下工作。


快照读和当前读

  • 快照读:读取记录数据的可见版本不加锁,普通的select语句都是快照读。

    1
    SELECT * FROM user WHERE id = 1;
  • 当前读:读取记录数据的最新版本显式加锁的都是当前读。

    如果两次查询中间有其他事务插入数据,就会产生幻读。InnoDB在RR隔离级别下,对读取的记录使用Next-key Lock,防止其他事务在间隙中插入数据

    1
    2
    3
    SELECT * FROM user WHERE id = 1 FOR UPDATE;

    SELECT * FROM user WHERE id = 1 LOCK IN SHARE MODE;

ReadView

ReadView是事务在进行快照读的时候生成的记录快照,用来做可见性判断。

ReadView保存了当前事务开启时所有活跃的事务列表,可以理解为不应该让当前事务看到的其他事务列表

  • m_ids

    当前系统中活跃(未提交)的读写事务ID,数据结构是一个LIst。不包括当前事务自身已提交的事务

  • m_low_limit_id

    目前出现过的最大的事务ID+1,即下一个将被分配的事务id。≥这个ID的数据版本均不可见

  • m_up_limit_id

    活跃事务列表m_ids中最小的事务ID,如果trx_ids为空,up_limit_id为low_limit_id。**<该ID的数据版本均可见**。

  • m_creator_trx_id

    生成该ReadView的事务的事务id。image-20240529171640883

    image-20240530171532266


MVCC实现原理

查询一条记录的过程:

  1. 获取事务自身的trx_id
  2. 获取ReadView
  3. 数据库中如果查询到数据,就到ReadView中的事务版本号进行比较
  4. 如果不符合ReadView的可见性规则,就需要undo log中记录的历史快照,直到返回符合规则的数据。

image-20240530170140599


MVCC能解决幻读吗