一.MySQL逻辑架构
先说下其架构吧,MySQL逻辑架构如下所示,最上层包括连接、线程处理,认证等。第二层是MySQL的核心服务,包括查询解析、分析、优化、缓存、内置函数(时间、日期 etc)、存储过程、触发器等。第三层就是存储引擎了,主要负责数据的存储和查询。
二.MySQL中的事务
我们接触比较多的存储引擎是InnoDB和MYISAM,其中InnoDB支持事务但是MYISAM不支持事务。MySQL5.X默认使用InnoDB作为其存储引擎,并且默认采用自动事务提交模式(AUTOCOMMIT),也就是说如果不显示开启一个事务,则每个查询都被当作一个事物执行提交操作。当然,我们可以通过设置来修改事物是否自动提交:
select @@autocommit; //查看当前数据库是否启用事务自动提交模式,1或ON表示启用,0或OFF表示禁用。
set @@autocommit = 1;//表示启用事务的自动提交模式。
set @@autocommit = 0;//表示关闭事务的自动提交模式。
还需要提及一点的是,InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时都可以执行锁定,锁只有在COMMIT或者ROLLBACK的时候才会释放,并且所有的锁在同一时刻被释放。这种属于隐式锁,InnoDB会根据隔离级别在需要的时候自动加锁。当然,InnoDB也支持通过特定的语句进行显示锁定,比如SELECT ... FOR UPDATE;
三.InnoDB的多版本并发控制(MVCC)
首先需要说明的是MVCC(Multi-Version Concurrency Control)的主要作用是提高读请求的并发性能,实现了非阻塞的读操作,属于乐观锁机制。
InnoDB的MVCC的具体实现是通过在每条记录后面添加额外的两个列来做的,分别为创建版本号(CREATE_VERSION)和删除版本号(DELETE_VERSION),每开启一个事务,系统的版本号都会自增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行对比。在REPEATABLE READ隔离级别下,MVCC具体操作如下:
操作类型 | 操作方式 | CREATE_VERSION | DELETE_VERSION | 备注 |
---|---|---|---|---|
INSERT | InnoDB存储引擎会为插入的这条数据保存当前系统版本号作为CREATE_VERSION,DELETE_VERSION不做操作 | 1 | - | 假设插入数据时当前系统版本号为0,那么插入数据则版本号变为1 |
UPDATE | 在InnoDB中更新其实底层是插入操作,插入一条新的记录,保存当前的系统版本号作为CREATE_VERSION,同时保存当前的系统版本号到原来旧的行记录作为DELETE_VERSION | 2 | - | 新插入的记录(因为又开启了一个新的事务,系统版本号变成2) |
1 | 2 | 旧的行记录(已无效) | ||
DELETE | 保存当前系统版本号作为DELETE_VERSION | 2 | 3 | 删除同样是开启新事物,系统版本号自增至3 |
SELECT | InnoDB查找的数据需要同时符合以下两条件: 1.CREATE_VERSION大于或等于当前系统版本号的行 2.数据行的DELETE_VERSION是未定义或者小于当前系统版本号 | 查询同样也需要开启一个事物,此时系统版本号从3自增至4,因为上面插入的这条记录的CREATE_VERSION=2 < 4 ,DELETE_VERSION = 3 < 4,发现满足第二个条件但是不满足第一个条件,所以上面的数据不能够被查询出来 |
InnoDB实现的MVCC的不足之处是需要额外维护两列,导致增加额外的存储空间。并且,MVCC只适用数据库的REPEATABLE READ和READ COMMITED两个隔离级别(READ UNCOMMITED的原理就是总是读取最新的行,而不是读取当前事务版本的数据行;SERIALIZABLE则会对所有读取的行进行加锁不符合乐观锁的机制)。