`

数据库脏读、不可重复读、幻象读

阅读更多

本文转载自:http://www.cnblogs.com/Sun_Blue_Sky/articles/2139996.html

 

数据库的事务隔离级别(TRANSACTION ISOLATION LEVEL)是一个数据库上很基本的一个概念。为什么会有事务隔离级别,SQL Server上实现了哪些事务隔离级别?事务隔离级别的前提是一个多用户、多进程、多线程的并发系统,在这个系统中为了保证数据的一致性和完整性,我们引入了事务隔离级别这个概念,对一个单用户、单线程的应用来说则不存在这个问题。

首先,我们来看一下高并发的系统中会存在哪些问题,为了便于理解我们以张三在招商银行的账号和存款为例。

一、准备工作:

1. 创建一个银行账号Table(只是为了说明问题,不考虑表的设计范式)
CREATE TABLE dbo.BankAccount
(
BankAccountId CHAR(16) NOT NULL, -- 银行账号
UserName NVARCHAR(32) NOT NULL, -- 用户
Balance DECIMAL(19, 2) NOT NULL, -- 余额
LastUpdate SMALLDATETIME NOT NULL
)
GO

2. 准备数据
INSERT INTO dbo.BankAccount
VALUES ('9555500100071120', N'张三', 10000.00, GETDATE()) -- 北京分行账号
INSERT INTO dbo.BankAccount
VALUES ('9555507551227787', N'张三', 20000.00, GETDATE()) -- 深圳分行账号
GO

3. 查看数据
SELECT * FROM dbo.BankAccount

二、应用场景

假设张三在招商银行开设了两个账号,一个是招商银行北京分行,一个是招商银行深圳分行,两个账号的余额分别是10,000和20,000。

1. 张三在网上做了一笔交易,交易额100,买方小王通过银行汇款100到张三的北京分行的账号(见下面左图),柜台操作人员向张三账号存入100(事务一),然后系统些操作日志(假设需要10秒,WAITFOR DELAY '00:00:10')正在此时张三在ATM查了一下账号上余额(事务二),发现已经是10100,于是回去准备发货,但是事务一在写操作日志时超时,这是事务回滚,存款交易被取消,钱退给了小王,这样张三查到的账号余额事实上是事务一还没有提交的数据,导致张三错误的认为已经收到交易款项。

数据库的事务隔离级别(TRANSACTION ISOLATION LEVEL)是一个数据库上很基本的一个概念。为什么会有事务隔离级别,SQL Server上实现了哪些事务隔离级别?事务隔离级别的前提是一个多用户、多进程、多线程的并发系统,在这个系统中为了保证数据的一致性和完整性,我们引入了事务隔离级别这个概念,对一个单用户、单线程的应用来说则不存在这个问题。

首先,我们来看一下高并发的系统中会存在哪些问题,为了便于理解我们以张三在招商银行的账号和存款为例。

一、准备工作:

1. 创建一个银行账号Table(只是为了说明问题,不考虑表的设计范式)
CREATE TABLE dbo.BankAccount
(
BankAccountId CHAR(16) NOT NULL, -- 银行账号
UserName NVARCHAR(32) NOT NULL, -- 用户
Balance DECIMAL(19, 2) NOT NULL, -- 余额
LastUpdate SMALLDATETIME NOT NULL
)
GO

2. 准备数据
INSERT INTO dbo.BankAccount
VALUES ('9555500100071120', N'张三', 10000.00, GETDATE()) -- 北京分行账号
INSERT INTO dbo.BankAccount
VALUES ('9555507551227787', N'张三', 20000.00, GETDATE()) -- 深圳分行账号
GO

3. 查看数据
SELECT * FROM dbo.BankAccount

二、应用场景

假设张三在招商银行开设了两个账号,一个是招商银行北京分行,一个是招商银行深圳分行,两个账号的余额分别是10,000和20,000。

1. 张三在网上做了一笔交易,交易额100,买方小王通过银行汇款100到张三的北京分行的账号(见下面左图),柜台操作人员向张三账号存入100(事务一),然后系统些操作日志(假设需要10秒,WAITFOR DELAY '00:00:10')正在此时张三在ATM查了一下账号上余额(事务二),发现已经是10100,于是回去准备发货,但是事务一在写操作日志时超时,这是事务回滚,存款交易被取消,钱退给了小王,这样张三查到的账号余额事实上是事务一还没有提交的数据,导致张三错误的认为已经收到交易款项。
dirtyread1 dirtyread2
一个事务读到另外一个事务还没有提交的数据,我们称之为脏读。
解决方法:把事务隔离级别调整到READ COMMITTED,即把右上图中的SET TRAN ISOLATION LEVEL READ UNCOMMITTED更改成下图中的SET TRAN ISOLATION LEVEL READ COMMITTED。这时我们重复上面的动作会发现事务二会一直等到事务一执行完毕再返回结果,因为此时事务以已经把自己的更改ROLLBACK了,所以事务二可以返回正确的结果。

dirtyread3

2. 张三先后两次查询某一账号的余额,在两次查询期间,小王完成了银行转账,导致两次的查询结果不同。

unrepeatable1unrepeatable2
一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。
解决方法:把事务隔离级别调整到REPEATABLE READ。在下图中使用SET TRAN ISOLATION LEVEL REPEATABLE READ。这时我们重复上面的动作会发现事务二会一直等到事务一执行完毕再返回结果。

unrepeatable3

3. 张三妻子先后两次查询张三招商银行所有账号的总余额,而在此期间张三在广州招商银行分行成功开设了一个账号,并存入5000,导致张三妻子两次查询的总余额不同,在此期间张三原有两个账号的余额均未发生改变。
serializable1 serializable2
一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读。
解决方法:把事务隔离级别调整到SERIALIZABLE。在下图中使用SET TRAN ISOLATION LEVEL SERIALIZABLE。这时我们重复上面的动作会发现事务二会一直等到事务一执行完毕再返回结果。

serializable3

三、总结

事务隔离级别是通过数据库的锁机制来控制的,在不同的应用场景需要应用不同的事务隔离级别,SQL Server默认的事务隔离级别是READ COMMITTED,默认的隔离级别,已经可以满足我们大部分应用的需求。

分享到:
评论

相关推荐

    数据并发的问题 (脏读、不可重复读、幻象读)和数据库锁机制

    数据并发的问题 (脏读、不可重复读、幻象读)和数据库锁机制

    华南理工大学2020年数据库实验4(SQLserver编写)

    4. **SERIALIZABLE**:最高隔离级别,防止脏读、不可重复读和幻象读,确保事务间的串行化执行。 【实验步骤】 1. 使用实验一提供的建库脚本和数据插入脚本来创建`Student`数据库。 2. 对每个事务隔离级别,设计...

    数据库四个级别 详解

    然而,由于其他事务可能在当前事务的不同阶段提交更改,所以可能出现“不可重复读”,即事务在不同时间读取同一数据时,结果可能不一致。 3. **可重复读(Repeatable Read)**: - 这个级别保证了在一个事务内部,...

    数据库系统并发控制及其实现

    - **可串行读(Serializable)**:最高隔离级别,完全避免脏读、不可重复读和幻象读,但可能导致更多的等待和锁冲突。 选择合适的隔离级别需要在数据一致性和系统性能之间找到平衡。 ##### 1.3.2 锁(Lock)机制 ...

    oracle和sql server两个数据库并发行和读一致性比较.pdf

    它确保在读取数据时,能看到的是一个一致性的视图,即使在高并发环境下,也能够避免脏读、不可重复读和幻象读等现象。这些现象通常是由并发操作未被妥善处理导致的。 #### 事务级别(Transaction Level) 事务级别...

    Oracle的事务及锁.docx

    然而,并发执行可能导致脏读、不可重复读和幻读等问题: - 脏读:一个事务读取了另一个未提交事务修改的数据,这在提交读隔离级别下会被阻止。 - 不可重复读:一个事务在不同时间读取同一数据时,由于其他事务的修改...

    数据库事务管理-PPT课件.ppt

    通过封锁(Locking)等技术,DBMS确保事务在执行时不会看到其他事务未提交的更改,从而避免了诸如丢失更新、脏读、不可重复读和幻读等问题。 4. **持久性**:持久性表示一旦事务提交,其对数据库的更改就会永久保存...

    mysql修改数据刷新页面直接显示

    这种隔离级别可以防止脏读,但不能防止不可重复读和幻象读。Oracle 等多数数据库默认都是该级别。 可重复读(Repeated Read)隔离级别可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB 默认级别。在 ...

    SQL数据库的并发控制.pdf

    2. **未确认的相关性(脏读)**:事务读取了另一个事务尚未提交的数据,如果该事务最终回滚,则读取的数据是无效的。 3. **不一致的分析(非重复读)**:同一个事务中多次读取同一行数据,但由于其他事务对该行数据...

    课件数据库系统原理复习要点

    - 并发问题:丢失更新、不可重复读、读脏数据、幻象读。 10. **ER图**: - 实体-关系模型,用于描述实体、属性和实体间的关系。 - 局部ER图合并:处理属性冲突、结构冲突和命名冲突。 - E-R图到关系模式的转换...

    mySQL教学事务和锁PPT教案学习.pptx

    7. **并发问题**:并发操作可能导致脏读、不可重复读和幻象读等问题。脏读是读取未提交的数据,不可重复读是两次读取同一数据得到不同结果,幻象读则是读取到了其他事务新插入的数据。此外,还有丢失更新问题,分为...

    Spring_事务基础知识[归纳].pdf

    - **不可重复读(Unrepeatable Read)**:事务A在不同时间读取了同一数据的不同版本,因为另一个事务B在这期间修改了数据并提交。 - **幻象读(Phantom Read)**:事务A在两次查询之间,有新的满足查询条件的数据被...

    数据库系统实现

    3.4.4 不能装入一个块中的记录 3.4.5 BLOBS 习题 3.5 记录的修改 3.5.1 插入 3.5.2 删除 3.5.3 修改 习题 3.6 小结 3.7 参考文献 第4章 索引结构 4.1 顺序文件上的索引 4.1.1 顺序文件 ...

    Spring框架+Spring中的事务

    - **ISOLATION_SERIALIZABLE**:最高隔离级别,完全避免脏读、不可重复读和幻象读,但性能开销较大。 #### 六、示例说明 以示例的形式解释不同隔离级别的差异有助于理解事务隔离级别的实际作用。例如,在`...

    MySQL 如何使用事务

    `REPEATABLE READ`隔离级别防止了脏读和不可重复读,但在某些情况下仍可能产生幻读。 #### 隔离级别设置 MySQL的默认隔离级别是`REPEATABLE READ`。要查看当前的隔离级别,可以运行`SELECT @@tx_isolation;`。设置...

    db2数据库入门教程(官方中文版)

    2.2 DB2 Express-C所不具备的功能...................................................................................23 2.2.1数据库分区......................................................................

    Oracle数据库绑定变量特性及应用

    Oracle数据库的绑定变量特性是其优化SQL性能的关键技术之一,对于构建高效、可扩展和稳定的数据库系统至关重要。本文将深入探讨绑定变量的原理、优势以及如何在实际应用中使用。 首先,为什么我们要使用绑定变量?...

    动吧模拟面试知识点汇总.pdf

    7. 数据库操作:涉及到数据库连接查询的种类和特点,以及事务相关的知识点,包括事务的定义、实现方式、四大特性(ACID)、隔离级别、脏读、不可重复读和幻象读概念。 8. 菜单模块:在面试中,可能会问及菜单模块的...

    db2数据库入门官方教程(中文版)

    2.2 DB2 Express-C所不具备的功能...................................................................................23 2.2.1数据库分区......................................................................

Global site tag (gtag.js) - Google Analytics