事务特性
简称acid
原子性 : 事务执行过程中,要么全部成功,要么全部失败
一致性 : 事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态
隔离性 : 多个事务同时使用相同的数据时,不会相互干扰
持久性 : 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
事务隔离级别
- 读未提交: 可以读取/修改别的事务未提交的数据;四种问题都没有解决
- 读已提交: 解决了脏写,脏读;
- 可重复读(默认) : 解决了脏写,脏读,不可重复读问题
- 串行化: 在事务持续期间,禁止其他事务对该表进行插入,删除,修改操作,所有的并发问题都可以避免
事务并发带来的问题
脏写
对未提交的事务中的数据进行修改, 事务最终提交,导致写失效.
脏读
读取未提交事务中的数据,就是脏数据.
不可重复读
在一个事务内多次读取同一个数据,数据值不同.
幻读
在一个事务内多次读取一张表,记录数发生变化.
MVCC(重点)
MVCC多版本并发控制,作用就是对不同事务隔离级别生成不同的ReadView,来解决并发带来的事务问题.
- 快照读
读取的是快照数据,不加锁的简单的select都是快照读;
是基于MVCC生成的快照;
所以不一定是最新的数据。 - 当前读
当前读是数据的最新版本;
如何保证读取的是最新?
加锁;保证其他事物不能修改当前数据;
select for update;
insert into
delete from
update
都会对数据加排他锁(写锁,间隙锁); - 隐藏字段
对于Innodb存储引擎,聚簇索引记录中都包含两个隐藏字段:
(1)trx_id :当前事务id
(2)roll_pointer :指向上一个版本数据的指针
每次对某条聚簇索引的数据进行修改,就会把旧版本的数据写UodoLog; - undoLog版本链

ReadView
- 读已提交 和 可重复读 隔离级别的事务,都是通过MVCC生成的快照实现;
"唯一不同的是 读已提交 和 可重复读 生成快照的时机不同" - 如何生成快照?
2.1 四个重要的参数
(1)creator_trx_id 当前事务的id(创建这个ReadView的id)
(2)trx_ids 未提交事务的id List
(3)up_limit_id 未提交事务的最小id
(4)low_limit_id 在生成当前ReadView时刻,系统中下个事务生成的id
2.2 如何生成
读已提交 和 可重复读都要保证 "读到的事务都是已经提交的事务"
所以 - 当被访问数据的事务的id<up_limit_id 一定可以被访问
- 当被访问数据的事务的low_limit_id>id>up_limit_id且不在trx_ids中,一定可以被访问
- 当被访问数据的事务的id>=low_limit_id不可以被访问
2.3 快照生成的时机
1.读已提交,在事务中每次的Select都会生成一个新的ReadView。
2.可重复度,在事务第一个Select就会生成一个ReadView,且以后的Select都使用这个ReadView