事务隔离机制

本文详细解释了事务隔离级别的概念,并介绍了四种主要的隔离级别:Read Uncommitted、Read Committed、Read Repeatable 和 Serializable。同时对比了Oracle和SQL Server在实现这些隔离级别上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务隔离级别:一个事务对数据库的修改与并行的另一个事务的隔离程度。

1、幻想读事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想。

2、不可重复读取事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同,这称为不可重复读。

3、脏读事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据,然后T1执行回滚操作,取消刚才的修改,所以T2所读取的行就无效,也就是脏数据。

4、第一类丢失更新

A事务撤销时,把已经提交的B事务的更新数据覆盖了。这种错误可能造成很严重的问题,通过下面的账户取款转账就可以看出来: 



第二类丢失更新

A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失



为了处理这些问题,SQL标准定义了以下几种事务隔离级别


Oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。所以Oracle不支持脏读

SQL标准所定义的默认事务隔离级别是SERIALIZABLE,但是Oracle 默认使用的是READ COMMITTED

为避免出现第二类更新丢失

sql_1:select 1 from dual for update;
sql_2:select 1 from dual for update;
sql_3:select 1 from dual for update nowait;

执行sql_1,不提交,表dual被锁

分支1):执行sql_2,sql_2被阻塞,等待sql_1提交

分支2):执行sql_3,因为有nowait,所以立即返回错误信息 "ORA-00054 : 资源正忙,但指定以NOWAIT方式获取资源"

总结:nowait关键字,通知Oracle该sql语句采用非阻塞的方式修改或删除数据,如果发现涉及到的数据被占有(被锁),则立即通知Oracle该资源被占用,返回错误信息



在SQL92标准中,事务隔离级别分为四种,分别为:Read UncommittedRead CommittedRead RepeatableSerializable

其中Read Uncommitted与Read Committed为语句级别的,而Read Repeatable与Serializable是针对事务级别的。

在Oracle和SQL Server中设置事务隔离级别的语句是相同的,都使用SQL92标准语法,即:

Set Transaction Isolation Level Read Committed

 

 1.SQL Server中的隔离级别及实现机制

 

  在SQL Server中提供了所有这四种隔离级别。

 

  Read Uncommitted

  一个会话可以读取其他事务未提交的更新结果,如果这个事务最后以回滚结束,这时的读取结果就可能是错误的,所以多数的数据库应用都不会使用这种隔离级别。

  Read Committed

  这是SQL Server的缺省隔离级别,设置为这种隔离级别的事务只能读取其他事务已经提交的更新结果,否则,发生等待,但是其他会话可以修改这个事务中被读取的记录,而不必等待事务结束,显然,在这种隔离级别下,一个事务中的两个相同的读取操作,其结果可能不同

  Read Repeatable

  在一个事务中,如果在两次相同条件的读取操作之间没有添加记录的操作,也没有其他更新操作导致在这个查询条件下记录数增多,则两次读取结果相同。换句话说,就是在一个事务中第一次读取的记录保证不会在这个事务期间发生改变。SQL Server是通过在整个事务期间给读取的记录加锁实现这种隔离级别的,这样,在这个事务结束前,其他会话不能修改事务中读取的记录,而只能等待事务结束,但是SQL Server不会阻碍其他会话向表中添加记录,也不阻碍其他会话修改其他记录(其他会话:不能修改当前会话读的数据,但是可以添加数据---》可以幻想读)

  Serializable

  在一个事务中,读取操作的结果是在这个事务开始之前其他事务就已经提交的记录,SQL Server通过在整个事务期间给表加锁实现这种隔离级别。在这种隔离级别下,对这个表的所有DML操作都是不允许的,即要等待事务结束,这样就保证了在一个事务中的两次读取操作的结果肯定是相同的。

 

  2.Oracle中的隔离级别及实现机制

 

  在Oracle中,没有Read Uncommitted及Repeatable Read隔离级别,这样在Oracle中不允许一个会话读取其他事务未提交的数据修改结果,从而避免了由于事务回滚发生的读取错误。Oracle中的Read Committed和Serializable级别,其含义与SQL Server类似,但是实现方式却大不一样。

 

  在Oracle中,存在所谓的回滚段(Oracle9i之前版本)或撤销段(Oracle9i版本),Oracle在修改数据记录时,会把这些记录被修改之前的结果存入回滚段或撤销段中,就是因为这种机制,Oracle对于事务隔离级别的实现与SQL Server截然不同。在Oracle中,读取操作不会阻碍更新操作,更新操作也不会阻碍读取操作,这样在Oracle中的各种隔离级别下,读取操作都不会等待更新事务结束,更新操作也不会因为另一个事务中的读取操作而发生等待,这也是Oracle事务处理的一个优势所在。

 Read Committed

  Oracle缺省的设置是Read Committed隔离级别(也称为语句级别的隔离),在这种隔离级别下,如果一个事务正在对某个表进行DML操作,而这时另外一个会话对这个表的记录进行读取操作,则Oracle会去读取回滚段或撤销段中存放的更新之前的记录,而不会象SQL Server一样等待更新事务的结束。

 Serializable

  在Serializable隔离级别(也称为事务级别的隔离),事务中的读取操作只能读取这个事务开始之前已经提交的数据结果。如果在读取时,其他事务正在对记录进行修改,则Oracle就会在回滚段或撤销段中去寻找对应的原来未经更改的记录(而且是在读取操作所在的事务开始之前存放于回滚段或撤销段的记录),这时读取操作也不会因为相应记录被更新而等待。


相关链接:http://blog.youkuaiyun.com/gaogaoshan/article/details/21158949  

MySQL的事务隔离机制是通过不同的隔离级别来控制事务并发执行时的数据可见性和一致性。隔离级别越高,事务之间的隔离程度越好,但性能开销也越大。SQL标准定义了四种常见的事务隔离级别,MySQL也支持这四种级别,并且每种级别都有其特定的实现原理。 ### 事务隔离级别 MySQL支持以下四种事务隔离级别: 1. **未提交读(Read Uncommitted)**:这是最低的隔离级别,允许一个事务读取另一个事务未提交的数据。这种级别可能导致脏读(Dirty Read),即读取到无效的或未提交的数据。 2. **提交读(Read Committed)**:该级别确保一个事务只能读取到其他事务已经提交的数据。它避免了脏读,但可能会出现不可重复读(Nonrepeatable Read)和幻读(Phantom Read)。 3. **可重复读(Repeatable Read)**:这是MySQL的默认隔离级别。它确保在同一个事务中多次读取同一数据时,结果是一致的,即使其他事务对数据进行了修改并提交。可重复读级别解决了不可重复读的问题,但可能仍然存在幻读。 4. **串行化(Serializable)**:这是最高的隔离级别,通过强制事务串行执行来避免所有并发问题。它完全隔离了事务之间的数据访问,避免了脏读、不可重复读和幻读,但性能开销最大。 ### 实现原理 MySQL的事务隔离机制主要依赖于其存储引擎(如InnoDB)来实现。InnoDB通过多版本并发控制(MVCC)和锁机制来实现不同级别的隔离性。 - **一致性读(Consistent Read)**:InnoDB使用多版本并发控制(MVCC)来提供一致性读。在`REPEATABLE READ`隔离级别下,事务中的所有一致性读都读取事务开始时的快照。而在`READ COMMITTED`隔离级别下,事务中的每个一致性读都会读取最新的快照版本。一致性读不会对表加锁,因此多个事务可以并发地修改数据。 - **锁机制**:InnoDB支持行级锁和表级锁。在`READ COMMITTED`和`REPEATABLE READ`级别,InnoDB使用行级锁来控制并发访问。在`SERIALIZABLE`级别,InnoDB会对所有读取操作加锁,从而强制事务串行化执行。 - **不可重复读与幻读**:在`READ COMMITTED`级别,由于每次一致性读都会刷新快照,因此可能会出现不可重复读。而在`REPEATABLE READ`级别,事务在整个生命周期内使用同一个快照,因此避免了不可重复读。至于幻读,在`REPEATABLE READ`级别,InnoDB通过间隙锁(Gap Lock)来防止其他事务插入新行,从而避免了幻读。 ### 隔离级别与并发问题的关系 | 隔离级别 | 脏读 | 不可重复读 | 幻读 | 丢失更新 | |---------------------|------|------------|------|----------| | 未提交读(Read Uncommitted) | 可能 | 可能 | 可能 | 可能 | | 提交读(Read Committed) | 不可能 | 可能 | 可能 | 可能 | | 可重复读(Repeatable Read) | 不可能 | 不可能 | 不可能 | 可能 | | 串行化(Serializable) | 不可能 | 不可能 | 不可能 | 不可能 | ### 设置隔离级别 在MySQL中,可以通过以下命令设置事务隔离级别: ```sql SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}; ``` 例如,将当前会话的隔离级别设置为`READ COMMITTED`: ```sql SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; ``` ### 总结 MySQL的事务隔离机制通过不同的隔离级别和实现原理来平衡数据一致性和并发性能。选择合适的隔离级别取决于具体的应用场景和对数据一致性的要求。较高的隔离级别可以提供更强的数据一致性,但可能会降低系统的并发性能[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值