事务特征ACID
- 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚,没有中间状态。它确保了数据的完整性。
- 一致性(Consistency):事务执行后,数据库从一个一致的状态转变为另一个一致的状态。执行事务前后,数据库中的数据满足所有定义的约束和规则。
- 隔离性(Isolation):并发执行的事务之间相互隔离,不会互相干扰。每个事务感觉就像是独立运行的,即使多个事务并发执行,也不能看到其他事务未提交的修改。
- 持久性(Durability):一旦事务被提交,其所做的修改将永久保存在数据库中,并且对系统的故障具有恢复能力。
脏读、不可重复读、幻读
- 脏读(Dirty Read):一个事务读取到了另一个事务未提交的数据,并且如果第一个事务回滚,则读取到的数据是无效的。
- 不可重复读(Non-Repeatable Read):一个事务在同一个查询中的多次读取可能会得到不同的结果,这是因为其他事务可能在两次读取之间提交了数据,导致数据不一致。
- 幻读(Phantom Read):一个事务在同一个查询中的多次读取可能会发现新插入的数据或已删除的数据,这是因为其他事务可能在两次读取之间插入了新数据或删除了现有数据。
事务隔离级别
- 读未提交(Read Uncommitted):最低的隔离级别,允许一个事务读取另一个事务尚未提交的数据。
- 读已提交(Read Committed):允许一个事务只读取已经提交的数据,避免了脏读问题。
- 可重复读(Repeatable Read):确保一个事务多次读取同一数据时结果一致,避免了不可重复读问题。
- 串行化(Serializable):最高的隔离级别,通过串行执行事务来避免任何并发问题,包括脏读、不可重复读和幻读。
事务隔离级别与脏读、不可重复读、幻读
主流数据库的事务隔离级别
- Oracle:默认的隔离级别是读已提交(Read Committed),支持其他隔离级别包括可串行化(Serializable)和只读(Read Only)。
- MySQL:默认的隔离级别是可重复读(Repeatable Read),支持其他隔离级别包括读未提交(Read Uncommitted)、读已提交(Read Committed)和串行化(Serializable)。
- PostgreSQL:默认的隔离级别是读已提交(Read Committed),支持其他隔离级别包括读未提交(Read Uncommitted)、可重复读(Repeatable Read)和可串行化(Serializable)。
事务隔离级别的使用场景
- 读未提交(Read Uncommitted):几乎不用,适用于对数据一致性要求较低的场景,如临时查询、非关键业务。例如,一个用户正在编辑一个文档,另一个用户可以在该文档未保存的情况下查看它。这种情况下,可以使用读未提交的隔离级别,允许其他用户读取未提交的数据。
- 读已提交(Read Committed):适用于大部分业务场景,避免脏读问题,同时提供较好的并发性能。例如,一个用户正在浏览一个在线商店的产品列表,另一个用户同时购买了一个产品并提交了订单。这种情况下,使用读已提交的隔离级别可以确保浏览用户只能看到已经提交的订单,避免了脏读问题。
- 可重复读(Repeatable Read):适用于要求较高数据一致性的场景,避免脏读和不可重复读问题,如账务系统、订单处理。例如,一个用户正在查看自己的银行账户余额,同时另一个用户正在转账给该用户。使用可重复读的隔离级别可以确保查看用户在整个查询过程中看到的余额保持一致,避免了不可重复读问题。
- 串行化(Serializable):适用于对数据一致性要求极高的场景,避免任何并发问题,如银行转账、库存管理。例如,一个用户正在从一个银行账户转账到另一个账户,同时另一个用户也在尝试转账到同一个账户。使用串行化的隔离级别可以确保每个转账操作依次执行,避免了并发问题。
需要注意的是,随着隔离级别的提高,事务的并发性能可能会下降,因为更严格的隔离级别需要更多的锁和资源管理。因此,在选择事务隔离级别时,需要权衡一致性和性能之间的关系,并根据实际业务需求和安全性要求进行选择。