# 事务
数据库事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
# 四个特性
# 原子性(Atomicity)
原子性是指事务中一个不可再分割的工作单元,事务中的操作要么全部执行,要么全部不执行。要么全部提交成功,要么全部失败回滚。即对于一个事务来说,不能只执行其中的一部分操作。
# 一致性(Consistency)
一致性是指在事务开始之前和事务结束之后,数据库的完整性约束都没有遭到破坏。数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
比如A给B转账,不论转账是否成功,A和B两人的存款总额是不会发生变化的。
# 隔离性(Isolation)
当多个事务同时并发访问时,事务之间是隔离的,一个事务不应该影响其它事务的运行结果。
# 持久性(Durability)
该事务对数据库所做的更改持久地保存在数据库之中,并不会发生回滚。即完成的事务是永久的部分,对系统的影响是永久存在的。
# 事务隔离级别
数据库定义了四个隔离级别:
- Serializable(序列化):Serializable是最高的事务隔离级别,花销也最高,性能很低,一般很少使用。在该级别下,事务顺序执行,可以避免脏读、不可重复读和幻读。
- Repeatable read(重复读):可以避免不可重复读,但有可能出现脏读和幻读。例如,只要事务开始,就不能再对该记录进行修改,所以会发生不可重复读。(MySQL默认隔离级别就是Repeatable read)
- Read committed(读提交):避免了脏读,但是有可能会发生不可重复读和幻读。(SQL Server和Oracle的默认级别就是Read committed)。
- Read uncommitted(读未提交):脏读、不可重复读和幻读都可能发生。
分别对应Connection
类中的四个常量:
TRANSACTION_SERIALIZABLE
TRANSACTION_REPEATABLE_READ
TRANSACTION_READ_COMMITTED
TRANSACTION_READ_UNCOMMITTED
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Serializable | ❎ | ❎ | ❎ |
Repeatable read | ❎ | ✅ | ✅ |
Read committed | ❎ | ✅ | ✅ |
Read uncommitted | ✅ | ✅ | ✅ |
- ✅:可能出现
- ❎:不会出现
# 隔离级别与锁的关系
# 脏读
一个事务读取到另外一个事务未提交的数据。
比如,A向B转账,A已经执行了转账语句,但是A还没有提交事务,这时候B读取数据时发现自己账户余额已经变多了。如果B通知A已经收到钱后,A又执行回滚事务(rollback),那么B再查看账户就会发现余额没有变多。
# 不可重复读
一个事务读取到另外一个事务已经提交的数据,即一个事务可以看到其它事务所做的修改。
例如,A查询数据库,而B修改了数据库的数据,这就会导致A多次查询数据库的结果都不一样。这就发生了在一个事务内多次读到的数据是不一样的,就称为不可重复读。
# 幻读(虚读)
一个事务读取到了别的事务插入的数据,导致前后读取不一致。
例如,事务A对一个表中的所有数据都进行了修改,同时,事务B向这个表插入了一行新的数据,那么操作事务A的用户就发现有一行新的数据没有修改到,前后读取不一致,仿佛产生了幻觉,叫做幻读(虚读)。
# 总结
脏读是不可容忍的,不可重复读和幻读在一定情况下是可以的。
← 索引 数据库的乐观锁和悲观锁 →