一、什么是事务,有什么用
数据库事务是指:作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功,要么全部失败,是一个不可分割的工作单位。事务的特性通常被概括为ACID属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
下面是mysql 中一个简单的事务例子:
-- 开启事务
start TRANSACTION
-- 转账操作
update users set money= money+100 where id = 1;
update users set money= money-100 where id = 2;
-- 查询结果
select * from article
-- 回滚,并关闭事务命令(如果操作失败就回滚事务)
-- ROLLBACK
-- 提交事务命令 (如果确认成功就提交事务)
COMMIT
二、事务的并发问题:
事务并发问题是指在多个事务同时执行时,由于事务之间的交织操作可能导致的数据不一致问题。这些问题主要包括脏读(Dirty Reads)、不可重复读(Non-repeatable Reads)和幻读(Phantom Reads),以及更新丢失(Lost Update)。下面分别对这些问题进行详细解释:
定义 | 备注 | |
---|---|---|
1. 脏读(Dirty Reads) | 一个事务读取到了另一个事务还没有提交的数据。 | 脏读的重点是未提交的事务 |
2、不可重复读(Non-repeatable Reads) | 一个事务内多次读取同一数据集合时,由于其他事务的更新操作,导致多次读取的结果不一致。 | 不可重读,和脏读的区别就是 有没有提交,如果数据提交,那么这个数据最终不一致,被定性为不可重复读 |
3. 幻读(Phantom Reads) | 一个事务重新执行一个查询,返回了初始查询中未出现的额外行,或者缺少了初始查询中出现的某些行。 | 幻读关注的是数据行的“增加”或“删除”,而不是数据行内容的改变 |
解决方案
针对上述事务并发问题,数据库系统提供了不同的事务隔离级别来解决:
事务名称 | 备注 |
---|---|
读未提交(Read unCommitted) | 百无禁忌,脏不脏的无所谓了 |
读已提交(Read Committed) | 只能读取到其他事务已经提交的数据。但不可重复读和幻读仍然可能发生 |
可重复读(Repeatable Read) | 保证在同一事务内多次读取同一数据的结果一致,可以避免脏读和不可重复读,但在某些数据库系统中可能无法解决幻读。 |
串行化(Serializable) | 最高级别的隔离,强制事务串行执行,可以避免脏读、不可重复读和幻读,但会严重影响并发性能。 |
不同的数据库系统可能对这些隔离级别的实现和支持有所不同,因此在实际应用中需要根据具体需求和数据库系统的特性来选择合适的隔离级别。
疑惑:已读提交为啥不能防止 不可重读读 (举例说明)
假设有两个事务A和B,事务A的隔离级别为读已提交。
- 事务A开启并读取数据X,此时X的值为100。
- 事务B随后修改数据X的值为200并提交。
- 事务A再次读取数据X,此时将看到X的值为200,与第一次读取的结果不一致,发生了不可重复读。
设置 事务级别:
-- 查看当前事务
select @@TRANSACTION_isolation
-- 设置事务方式
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE