1.前置问题
- 什么是事务?事务的特性?
- 隔离级别有几种?为什么要有不同的隔离级别?
- 隔离级别是会话级的吗?
- mvcc是什么?为什么要有mvcc?
- mvcc和隔离级别的关系?
- mvcc的两种同构模型?
- redo log和undo log的区别?
2. 事务
应用系统在操作数据库时,往往需要进行组合操作,事务的存在是把这种组合操作视为一个原子操作,要么全部执行成功,要么全不执行。事务通过原子性来保证数据库状态的一致性。
事务四个特性
1)原子性:在事务中的数据库操作视为一个整体,要么全部执行,要么全不执行,避免只执行了部分操作,导致数据不一致;
2)一致性:在事务操作前和操作后,数据库的数据始终处于一致性状态。例如,转账操作,需要保证转账前后,转账双方的总额不变;
3)隔离性:也称并发控制;多个事务并发访问数据库时,不同事务的操作在执行时要相互隔离,在提交前对其他事务不可见;
4)持久性:事务一旦提交,就是永久的。即便数据库宕机也能恢复。
3. 事务隔离性
考虑到并发的性能,MySql等数据库在实现隔离性性的时候并没有完全真正的隔离。目前有四种事务隔离级别标准:
insert into t (id, name) values(1, "wang") // 初始化语句
1)读未提交
一个事务读到了另一个事务未提交的修改,这种现象被称为脏读;
时间顺序 | 事务一 | 事务二 |
---|---|---|
1 | BEGIN | |
2 | select name from t where id = 1 // 结果为“wang” |
BEGIN |
3 | update t set name="王" where id = 1 | |
4 | select name from t where id = 1 // 结果为“王” |
|
5 | COMMIT | COMMIT |
2)读已提交
一个事务读到了另一个事务已提交的修改,这种现象被称为不可重复读;
时间顺序 | 事务一 | 事务二 |
---|---|---|
1 | BEGIN | |
2 | select name from t where id = 1 // 结果为“wang” |
BEGIN |
3 | update t set name="wang" where id = 1 | |
4 | select name from t where id = 1 // 结果为“wang” |
|
5 | COMMIT | |
6 | select name from t where id = 1 // 结果为“王” |
|
7 | COMMIT |
3)可重复读
一个事务读取的结果不会受另一个事务(无论是否提交)影响。
时间顺序 | 事务一 | 事务二 |
---|---|---|
1 | BEGIN | |
2 | select name from t where id = 1 // 结果为“wang” |
BEGIN |
3 | update t set name="wang" where id = 1 | |
4 | select name from t where id = 1 // 结果为“wang” |
|
5 | COMMIT | |
6 | select name from t where id = 1 // 结果为“wang” |
|
7 | COMMIT |
但是可重复读无法解决幻读问题,即当事务A读取某个范围的记录时,事务B在该范围内插入了新的记录,那么事务A再次读取该范围记录时,就会发现新增了记录。
4)串行化
数据库强制事务串行执行来避免并发问题。
附:隔离级别表
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | Y | Y | Y |
读已提交 | N | Y | Y |
可重复读 | N | N | Y |
串行化 | N | N | N |
4. InnoDb事务隔离性的实现
InnoDB通过MVCC(多版本并发控制机制)来实现读未提交,读已提交,可重复读级别的非阻塞读。并且通过间隙锁可使可重复读级别避免部分幻读问题。
1)MVCC的InnoDB实现
2)RR级别下,通过间隙锁解决部分幻读问题
5. redo log和undo log
redo log | undo log | |
---|---|---|
作用 | 保证事务的持久性 | 帮助事务回滚和支持mvcc功能 |
记录内容 | 物理日志,记录的是页的物理修改操作 | 逻辑日志,根据每行记录进行记录 |
参考
- MySql技术内幕 InnoDB存储引擎 第七章
网友评论