在数据库系统中,隔离
是定义一个操作对数据所做的改变如何/何时对其它的并行
操作可见。
隔离并不改变锁本身的行为,而是通过实行不同的锁机制实现的。比如是否加锁,加多长时间的锁,加什么类型的锁等。同时,也会影响排它情况下的可见性(见read uncommited)。
隔离级别
数据库系统有四个隔离级别(大多数数据库默认级别为read commited)。对数据库使用何种隔离级别要审慎分析,因为
1. 维护一个最高的隔离级别虽然会防止数据的出错,但是却导致了并行度的损失,以及导致死锁出现的可能性增加。
2. 然而,降低隔离级别,却会引起一些难以发现的bug。
SERIALIZABLE(序列化)
添加范围锁(比如表锁,页锁等,关于range lock,我也没有很深入的研究),直到transaction A结束。以此阻止其它transaction B对此范围内的insert,update等操作。
幻读,脏读,不可重复读等问题都不会发生。
REPEATABLE READ(可重复读)
对于读出的记录,添加共享锁直到transaction A结束。其它transaction B对这个记录的试图修改会一直等待直到transaction A结束。
可能发生的问题:当执行一个范围查询时,可能会发生幻读。
READ COMMITTED(提交读)
在transaction A中读取数据时对记录添加共享锁,但读取结束立即释放。其它transaction B对这个记录的试图修改会一直等待直到A中的读取过程结束,而不需要整个transaction A的结束。所以,在transaction A的不同阶段对同一记录的读取结果可能是不同的。
可能发生的问题:不可重复读。
READ UNCOMMITTED(未提交读)
不添加共享锁。所以其它transaction B可以在transaction A对记录的读取过程中修改同一记录,可能会导致A读取的数据是一个被破坏的或者说不完整不正确的数据。
另外,在transaction A中可以读取到transaction B(未提交)中修改的数据。比如transaction B对R记录修改了,但未提交。此时,在transaction A中读取R记录,读出的是被B修改过的数据。
可能发生的问题:脏读。
问题
我们看到,当执行不同的隔离级别时,可能会发生各种各样不同的问题。下面对它们进行总结并举例说明。
幻读
幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一个查询不相同。
发生的情况:没有范围锁。
例子:
事务1 |
事务2 |
SELECT
* FROM
users
WHERE
age BETWEEN
10
AND
30
;
|
|
|
INSERT
INTO
users VALUES
(
3
, 'Bob'
, 27
)
;
|
SELECT
* FROM
users WHERE
age BETWEEN
10
AND
30
;
|
如何避免:实行序列化隔离模式,在任何一个低级别的隔离中都可能会发生。
不可重复读
在基于锁的并行控制方法中,如果在执行select时不添加读锁,就会发生不可重复读问题。
在多版本并行控制机制中,当一个遇到提交冲突的事务需要回退但却被释放时,会发生不可重复读问题。
事务1 |
事务2 |
SELECT
* FROM
users WHERE
id = 1
;
|
|
|
UPDATE
users SET
age = 21
WHERE
id = 1
;
COMMIT; /* in multiversion concurrency*/
control, or lock-based READ COMMITTED *
|
SELECT
* FROM
users WHERE
id = 1
;
|
|
|
COMMIT; /* lock-based REPEATABLE READ */
|
在上面这个例子中,事务2提交成功,它所做的修改已经可见。然而,事务1已经读取了一个其它的值。在序列化和可重复读的隔离级别中,数据库管理系统会返回旧值,即在被事务2修改之前的值。在提交读和未提交读隔离级别下,可能会返回被更新的值,这就是“不可重复读”。
有两个策略可以防止这个问题的发生:
1. 推迟事务2的执行,直至事务1提交或者回退。这种策略在使用锁时应用。(悲观锁机制,比如用select for update为数据行加上一个排他锁)
2. 而在多版本并行控制中,事务2可以被先提交。而事务1,继续执行在旧版本的数据上。当事务1终于尝试提交时,数据库会检验它的结果是否和事务1、事务2顺序执行时一样。如果是,则事务1提交成功。如果不是,事务1会被回退。(乐观锁机制)
脏读
脏读发生在一个事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的是无效的数据。这跟不可重复读类似,但是第二个事务不需要执行提交。
事务1 |
事务2 |
SELECT
* FROM
users WHERE
id = 1
;
|
|
|
UPDATE
users SET
age = 21
WHERE
id = 1
|
SELECT
FROM
users WHERE
id = 1
;
|
|
|
COMMIT; /* lock-based DIRTY READ */
|
分享到:
相关推荐
介绍数据库事务的四种隔离级别,比较不同隔离级别的区别和影响
事务隔离级别 课程目标 了解 —— 事务隔离级别的概念; 理解 —— 事务隔离的四种级别; 掌握 —— 事务隔离级别的设置; 事务隔离级别 事务隔离:每一个事务都有一个所谓的隔离级,它定义了用户彼此之间隔离和交互...
数据库事务和隔离级别
查询:默认事务隔离级别 mysql> select @@tx_isolation;当前会话的默认事务隔离级别 mysql> select @@session.tx_isolation;当前会话的默认事务隔离级别 mysql> select @@global.tx_isolation;全局的事务隔离级别
### 数据库事务隔离级别详解 #### 一、引言 在多用户共享的数据库系统中,为了保证数据的一致性和准确性,必须对并发事务进行控制。数据库事务隔离级别是用来管理多个事务之间相互影响的程度,主要解决的问题包括脏...
数据库事务隔离级别是确保数据一致性和完整性的重要机制。通过合理设置事务隔离级别,可以在保证数据一致性的同时,优化数据库的并发性能。开发者需要根据具体的应用场景和业务需求,选择最合适的事务隔离级别,并在...
以下是对MySQL数据库事务隔离级别的详细解释。 1. **丢失更新**:在并发环境下,一个事务的更新可能被另一个事务的更新覆盖,导致前一个事务的更改丢失。 2. **脏读**:一个事务读取到了另一个事务还未提交的数据...
MySQL数据库的事务隔离级别是数据库管理系统中用于控制事务处理中并发操作的重要机制。在多用户同时访问数据库的情况下,事务隔离级别能够确保数据的一致性和完整性,避免并发操作带来的各种问题,如脏读、不可重复...
Spring 框架提供了一套完善的事务管理机制,其中包含了多种事务传播属性和事务隔离级别。这些特性使得在处理数据库操作时,能够更好地控制事务的边界和行为,从而确保数据的一致性和完整性。 首先,我们来看一下...
事务隔离级别是数据库系统用来解决并发问题,保证数据正确性的一种策略。MySQL数据库提供了四种不同的事务隔离级别,它们分别是读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable ...
以下是四种标准的事务隔离级别及其特点: 1. 未授权读取(Read Uncommitted): 这是最低的隔离级别,允许脏读取,但不允许更新丢失。在这个级别下,事务可能会读取到未提交的数据,存在数据不一致的风险。虽然...
MySQL事务隔离级别是数据库管理系统中一个非常重要的概念,它关系到数据的一致性和并发性能。在MySQL中,事务被用于确保数据库操作的原子性、一致性、隔离性和持久性(ACID特性)。事务隔离级别主要涉及四个方面:读...
事务隔离级别是指数据库事务的隔离级别,用于控制事务之间的隔离度。Java 中有五种事务隔离级别,分别是: 1. ISOLATION_DEFAULT:这是 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别...
数据库事务与隔离级别 数据库事务是指一系列操作的集合,作为一个单元执行,以维护数据库的一致性和完整性。事务必须具备四大特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性...
MySQL数据库管理系统提供了四种事务隔离级别来处理事务并发中可能遇到的问题。事务并发问题通常包括脏读、不可重复读和幻读。 一、事务的基本要素(ACID) 事务具有四个基本要素,即原子性(Atomicity)、一致性...
在SQL SERVER和ORACLE中,事务隔离级别是不同的,它们决定了并发操作时数据的可见性和一致性。SQL SERVER提供了四种隔离级别:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable ...
数据库提供了四种常见的事务隔离级别: - **Read Uncommitted(读取未提交内容)**:这是最低的隔离级别,允许事务读取其他未提交的更改。这可能导致脏读问题。 - **Read Committed(读取提交内容)**:在这个...
本资料主要探讨的是Spring支持的数据库事务传播属性和事务隔离级别。 一、事务传播属性 1. REQUIRED(默认):如果当前存在事务,则加入该事务;如果没有事务,则创建一个新的事务。这是最常见的事务定义,适用于...