事务

InnoDB的事务符合ACID特性:

  • 原子性 atomicity
  • 一致性 consistency
  • 隔离性 i
  • 一致性 d

事务通过redo log(重做日志)和 undo log(回滚日志)实现。
redolog保证事务的原子性和持久性,undolog保证事务的一致性。redolog是物理操作,记录页的修改操作,undolog是逻辑日志,根据每行记录进行记录。

实现原理

在事务提交前,会先将事务的所有的日志写入到重做日志文件进行持久化。

undolog

回滚操作用到undolog,undolog记录了写逻辑,但是不会改变数据结构和物理大小,回滚时,只是做了所有与之前相反的工作。

除了回滚操作,undolog另一个作用就是mvcc。当用户读取一条记录时,若该记录已被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。

当事务提交时,innoDB会做以下两件事:
1.将undo放入列表,共purge使用。
2.判断undolog所在页是否可以重用,若可以分配给下个事务使用。

事务隔离级别

SQL标准4个级别

read uncommitted 未提交读

这个级别; 事务的修改即使没有提交,对其他事务也是可见的。可以读取其他事务未提交的数据,称之为脏读。

read committed 提交读(不可重复读)

这个级别满足隔离性的定义。一个事务只能看见已经提交的事务所做的修改。但是同一事务可能对数据修改,所以同一select可能返回不同结果。

read repeatable 可重复读

innorDB通过多版本并发控制 MVCC 解决。每个事务对应一个事务序号,每个序号对应undo日志。

幻读,是指某个事务前后两次查询同一个范围的时候,后一个查询看到了前一次查询没有看到的行。

Serializable 可串行化

锁,所以导致大量的超时和锁争用问题。 场景是确保数据一致性并且没有并发。

MVCC

mvcc(多版本并发控制),可以认为是一个行级锁的变种,但是在某些情况下避免了加锁操作,因此开销更低。

实现

mvcc的实现是通过保存数据在某个时间点的快照来实现的。也就是不管执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对每一张表,每一时刻看到的数据可能不一样。
innoDB的mvcc,是通过在每行记录后面保存两个隐藏的列来实现的。一个保存行的创建时间,一个保存行的过期时间,不是实际时间,而是版本号。每开始一个新的事务,版本号会随之递增。看一下mvcc是如何操作的:

SELECT

根据两个条件检查每条记录:

  1. 只查早于当前事务版本的数据行(也就是行的版本号小于或等于事务版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或修改过的。
  2. 行的删除版本要么未定义,要么大于当前事务版本号,这样可以确保事务读取的行,在事务开始前未被删除。

INSERT

为新插入的每一行保存当前系统版本号作为行版本号。

DELETE

为删除的每一行保存当前系统版本号作为行的删除版本号。

UPDATE

innoDB为新插入的行,保存当前系统版本号作为行版本号,同时,保存当前系统版本号到原来行的删除版本号。

幻读与间隙锁

幻读,是指某个事务前后两次查询同一个范围的时候,后一个查询看到了前一次查询没有看到的行。
说明:
1.在rr隔离级别下,普通的查询是快照读,快照读是看不到其他事务插入的数据的,因此,幻读在”当前读“下才会出现。
2.update导致的当前读读到之前为读到的数据,不是幻读,幻读只针对于新插入的行。

通过间隙锁(gap lock)策略防止幻读出现,不仅仅锁定查询涉及的行,还会对索引中的间隙锁定,防止幻影行的插入。
间隙锁和行锁合成next-key lock,每个next-key lock是前开后闭区间。

标签: none

添加新评论