基础总览
ACID:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
脏读:读到了其他事务未提交的数据;
不可重复读:同一事务内,两次相同的查询返回了不同的结果;
幻读:主要针对于新增和删除,在A对一批数据进行修改后,未提交时,B事务新增了一条记录,导致A好像少修改了一条数据一样;
隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交 | 会 | 会 | 会 |
读已提交 | 不 | 会 | 会 |
可重复读(默认) | 不 | 不 | 会 |
串行化 | 不 | 不 | 不 |
事务实现原理
基本概念
- LBCC:基于锁的并发控制;
- MVCC:多版本的并发控制;
MVCC相关概念
MVCC增加了两个隐藏列,一个记录事务ID(DB_TRX_ID),一个记录回滚指针(DB_ROLL_PT);
- DB_TRX_ID:事务ID,依次递增;
- DB_ROLL_PT:指向上一个版本undo log的指针,会形成undo log history list;
- Undo log:事务的备份日志,insert和update都会产生undo log;
- Read view:一致性视图,MVCC下,每次读都会产生read view;
- Purge:undo log的清理线程,按照配置策略来清理undo log;
- m_ids:当前活跃的事务ID列表;其中,最大的ID是max_id,最小的min_id;
- DML:SELECT、UPDATE、INSERT、DELETE;
- DDL:比DML要多,主要的命令有CREATE、ALTER、DROP等;
read view读取原则(拿当前事务的事务ID来比较):
- 小于min_Id 数据可见
- 大于max_Id 数据不可见
- 在min_Id和max_Id之间
- 若row tx-id在数组中,代表是由还没提交事物生成的,不可见
- 若row tx-id不在数组中,代表是由已经提交的事物生成,可见
(如果数据不可见,会根据版本链的DB_ROLL_PT指针找到上一条数据,直到找到可见的数据)
快照读:
RR级别下,普通的select就是快照读;
当前读:
select…lock in share mode(读锁)
select…for update(悲观锁)
update,delete,insert
以上都是当前读;
间隙锁(record lock) + 行锁(gap lock) = 临键锁(next key lock)
- 临键锁是左开右闭的区间;
- 加锁的基本单位是临键锁;
- 唯一索引 等值查询,临键锁升级为行锁;
- 索引等值查询 不存在的值,向右查询第一个不满足需求的值,临键锁降级为间隙锁;
- 索引范围查询会产生临键锁;
基础概念介绍完了,下面开始进入正题:
读未提交
- 不加锁,性能最好;
读已提交(RC)
- 每次select都会生成一次新的read view;
- RC级别下,不会加间隙锁;
可重复读(RR)
- 一直沿用第一次select产生的read view,当前事务session生效;
- select不加锁时,是快照读,不会产生幻读;
- update没有命中索引时,会锁全表;
- insert只加意向锁(隐式锁),只有发生冲突时才加锁;
- 快照读与当前读 混合使用时,会产生幻读;
串行化
- 都是悲观锁;