事务的ACID属性
- Atomicity原子性
- Consistency一致性:从实际的业务逻辑上来说,最终结果是对的,是跟期望的结果完全符合的,比如转账的加减
- Isolation隔离性
- Durability持久性:事务一旦提交,数据会持久化到硬盘,他对数据库的改变是永久性的
四大隔离级别★
脏读 Dirty read | 不可重复读 Non repeatable read | 幻读 Phantom read | |
---|---|---|---|
读未提交 Read uncommited | √ | √ | × |
读已提交 Read commited | × | √ | × |
可重复读 Repeatable read | × | × | √ |
穿行 Serializable | × | × | × |
MVCC
Multi-Version Concurrency Control 多版本并发控制,为每个修改保存一个版本
解决了脏读、不可重复读、幻读问题,但无法解决更新丢失问题
在InnoDB中的实现:即使在有读有写的冲突中,也能做到不加锁,非阻塞并发读
当前读:会对读取的记录加锁,读取最新版本
1
2
3
4
5select lock in share mode //共享锁
select for update
update
insert
delete //排他锁快照读:不加锁的非阻塞读,快照读可能读到的不是最新版本
1
select
实现原理
三个隐藏字段
- DB_TRX_ID: 记录最近修改该行的事务id
- DB_ROLL_PTR: 回滚指针,指向该记录的上一个版本,用于配合undo log
- DB_ROW_ID: 隐藏的主键,若没有定义主键,则会自动生成主键
undo log
- 事务1执行insert
.
- 事务2执行update,修改时会加排他锁
.
- 事务3执行update,同理
.
形成链表
read view
快照读时会生成Read View视图,有三个全局属性
- trx_list: Read View生成时刻系统正活跃的事务id
- up_limit_id: trx_list中id的最小值
- low_limit_id: Read View生成时刻系统尚未分配的下一个事务id
事务1 | 事务2 | 事务3 | 事务4 |
---|---|---|---|
start transaction | start transaction | start transaction | start transaction |
… | … | .. | update and commit |
… | select | … | … |
.
.
问:事务2能否看到事务4的提交?
执行比较规则:
1 | if(DB_TRX_ID < up_limit_id){可见} |
- RR级别使用的Read View始终是第一次快照读时生成的Read View
- RC级别每次快照读都会生成一个新的Read View