数据库相关知识点
四. 事务
1. 为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性 的方法。
2. 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干 扰。
3. 事务是⼀个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从⼀种⼀致 性状态变到另⼀种⼀致性状态。事务是逻辑上的⼀组操作,要么都执行,要么都不执行。
4.1 事务四大特性
1. 原⼦性 (Atomicity)
事务是最小的执行单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作用。
eg: A给B转了100,A余额减100,刚转完系统崩溃,B收到钱款这一操作没有执行,则整个事务回滚,100元退还到A的余额。
2. 一致性 (Consistency)
确保数据库从一致状态转到另一个一致状态。
eg:转账行为中,一个人减了50元,另外一个人就应该加上这50元,而不能是40元。其他一致状态的含义是数据库中的数据应满足完整性约束,例如字段约束不能为负数,事务执行完毕后的该字段也同样不是负数。
3. 隔离性 (Isolation)
多个事务并发执行时,一个事务的执行应该不受其他事务执行的影响。
eg:A给B转100元和C给B转100元是独立的。
4. 持久性 (Durability)
成功执行的事务产生的结果应该被永久保留在数据库中。
4.2 脏读?幻读?不可重复读
1. 脏读 (Drity Read)
某个事务已更新⼀份数据,另⼀个事务在此时读取了同⼀份数据,由于某些原因,前⼀个 RollBack了操作,则后⼀个事务所读取的数据就会是不正确的。
2. 幻读(Phantom Read)
在⼀个事务的两次查询中数据笔数不⼀致,例如有⼀个事务查询了⼏列(Row)数据,⽽另 ⼀个事务却在此时插⼊了新的⼏列数据,先前的事务在接下来的查询中,就会发现有⼏列数据是它先前所没有的。
3. 不可重复读(Non-repeatable read)
在⼀个事务的两次查询之中数据不⼀致,这可能是两次查询过程中间插⼊了 ⼀个事务更新的原有的数据。
4.3 事务的隔离级别
为了达到事务的四⼤特性,数据库定义了4种不同的事务隔离级别,由低到⾼依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这⼏类问题。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ-UNCOMMITTED(读取未提交): | √ | √ | √ |
READ-COMMITTED(读取已提交) | × | √ | √ |
REPEATABLE-READ(可重复读) | × | × | √ |
SERIALIZABLE(可串⾏化) | × | × | × |
SQL 标准定义了四个隔离级别:
- READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复
读仍有可能发⽣。 - REPEATABLE-READ(可重复读): 对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修
改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。 - SERIALIZABLE(可串⾏化): 最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事
务之间就完全不可能产⽣⼲扰,也就是说,该级别可以防⽌脏读、不可重复读以及幻读。
注意:
1. 这⾥需要注意的是:Mysql 默认采⽤的 REPEATABLE_READ隔离级别 Oracle 默认采⽤的 READ_COMMITTED隔离级别。
2. 事务隔离机制的实现基于锁机制和并发调度。其中并发调度使⽤的是MVVC(多版本并发控制),通过保存修改的旧版本信息来⽀持并发⼀致性读和回滚等特性。
3. 因为隔离级别越低,事务请求的锁越少,所以⼤部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内 容):,但是你要知道的是InnoDB 存储引擎默认使⽤ REPEATABLE-READ(可重读)并不会有任何性能损失。
4. InnoDB 存储引擎在 分布式事务 的情况下⼀般会⽤到SERIALIZABLE(可串⾏化)隔离级别。