一、ACID特性
- 原子性
- 一致性
- 隔离性
- 持久性
二、事务隔离级别
- 读未提交:一个事务还未提交时,这个事务对数据的改动,其他事务就可见
- 读已提交:一个事务提交以后,这个事务对数据的改动,其他事务才可见
- 可重复读:一个事务在执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。
- 串行化:顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行
三、Mysql读取数据方式
在读取数据时,根据事务隔离级别的不同,会在不同的时刻点创建视图,访问的时候以视图的逻辑结果为准。如果是可重复读的隔离级别,视图是在事务启动时创建,读已提交是在SQL语句开始执行时创建视图。读未提交是没有视图的概念的,所以数据对其他事务可见。串行化则是直接加锁避免并发访问。
四、事务隔离的实现
-
同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。
-
在MySQL中,每条记录的更新都会同时记录一条回滚操作。
-
尽量不要使用长事务:会占用锁资源,占用大量的内存空间。5.5及之前会记录大量的回滚段,回滚段被清理后,文件也不会变小。
五、事务启动方式
Begin/Start Transaction启动方式,一致性视图是在执行第一个快照读语句时创建的;
Start transaction with consistent snapshot启动方式,一致性视图是在执行 start transaction with consistent snapshot 时创建的。
六、视图的概念
- view:是用查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。
- 一致性读视图(consistent read view):是InnoDB在是实现MVCC时用到的,用于支持RC和RR隔离级别的实现。没有物理结构,作用是事务执行期间用来定义我能看到什么数据。
事务启动时(事务id严格递增),就能看到所有已提交的事务,会对数据库生成一个快照,通过数据版本id实现。但是之后的所有的事务的更新对当前事务不可见。InnoDB 为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在“活跃”的所有事务 ID。“活跃”指的就是,启动了但还没提交。
数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。这个视图数组和高水位,就组成了当前事务的一致性视图(read-view)。低于低水位的事务表示已提交,数据可见。高于高水位的事务表示未开启,数据不可见。处于高水位和低水位之间的事务,表示事务已开启,但是未提交,如果数据的版本处于这个区间,则表示未提交,数据不可见,需要通过undolog向前查找直至找到已提交的事务。如果不处于且小于低水位,则表示已提交,数据可见。
数据库中的每一行数据,都可能会有多个版本(row),每个版本都有自己的版本ID(row trx_id数据版本的事务id),通过undo log 查询数据的历史版本。