返回顶部
首页 > 资讯 > 数据库 >SQL Server中四类事务并发问题的示例分析
  • 785
分享到

SQL Server中四类事务并发问题的示例分析

2024-04-02 19:04:59 785人浏览 安东尼
摘要

这篇文章将为大家详细讲解有关SQL Server中四类事务并发问题的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。sql Server中四类事务并发问题的实例再现

这篇文章将为大家详细讲解有关SQL Server中四类事务并发问题的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

sql Server中四类事务并发问题的实例再现

  首先,让我们先来了解一下并行问题以及事务隔离级别这两个概念。
数据库中,假设如果没有定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题。并发问题包括: 

  • 丢失或覆盖更新。

  • 未确认的相关性(脏读)。

  • 不一致的分析(非重复读)。

  • 幻像读。 

下面让我们稍花点时间来解释一下这四类问题:
1、丢失更新
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。


2、未确认的相关性(脏读)
当第二个事务选择其它事务正在更新的行时,会发生未确认的相关性问题。第二个事务正在读取的数据还没有确认并且可能由更新此行的事务所更改。

3、不一致的分析(非重复读)
当第二个事务多次访问同一行而且每次读取不同的数据时,会发生不一致的分析问题。不一致的分析与未确认的相关性类似,因为其它事务也是正在更改第二个事务正在读取的数据。然而,在不一致的分析中,第二个事务读取的数据是由已进行了更改的事务提交的。而且,不一致的分析涉及多次(两次或更多)读取同一行,而且每次信息都由其它事务更改;因而该行被非重复读取。

4、幻像读
当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。

  上述四个问题都会引起数据的不一致性。我们把事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了 SQL
Server 使用的锁定行为。

  SQL-92 定义了下列四种隔离级别,SQL Server 支持所有这些隔离级别:

  • READ UNCOMMITTED---未提交读(事务隔离的最低级别,仅可保证不读取物理损坏的数据)。

  • READ COMMITTED---提交读(SQL Server 默认级别)。

  • REPEATABLE READ---可重复读。

  • SERIALIZABLE---可串行读(事务隔离的最高级别,事务之间完全隔离)。

下表(1)列出了四种隔离级别允许不同类型的行为。

隔离级别脏读不可重复读取幻像
未提交读
提交读
可重复读
可串行读


为了再现以上四类问题,我们必须做一些准备工作:
1、请用下面的脚本创建测试用的表。

--创建测试用数据库test
CREATE DATABASE test
Go
--创建测试用表
USE test
GO
CREATE TABLE 帐户表
(
帐号 CHAR(4),
余额 INT
)
GO
INSERT 帐户表
SELECT 'A',100
UNION ALL
SELECT 'B',200


2、请开启两个查询分析器程序,意在开启两个连接,模拟两个并行的事务。以下简称连接一和连接二。
测试正式开始:
(1)丢失更新的再现

先看下面这个例子:

--在第一个连接中执行以下语句

BEGIN TRAN
UPDATE 帐户表 SET 余额=101 WHERE 帐号='A' 
WaiTFOR DELAY '00:00:10' --等待10秒
COMMIT TRAN

--接着马上使用第二连接执行下面的语句

BEGIN TRAN
UPDATE 帐户表 SET 余额=102 WHERE 帐号='A' 
COMMIT TRAN


我们会发现第二个连接里面的事务不能立刻执行,必须等待第一连接的事务完成之后才能执行下去。
这样就避免了“丢失更新”的问题,否则的话就会产生“丢失更新”的问题了。

丢失更新的问题是最为严重的一类问题,由表一可知,无论使用哪一种事务隔离级别,都不允许丢失更新的问题,因此该类问题无法再现。

(2)未确认的相关性(脏读)的再现
由表1可知,当事务的隔离级别为未提交读(READ UNCOMMITTED)的时候,允许脏读。

--在第一个连接中执行以下语句

BEGIN TRAN
UPDATE 帐户表 SET 余额=103 WHERE 帐号='A' 
WAITFOR DELAY '00:00:10' --等待10秒
UPDATE 帐户表 SET 余额=104 WHERE 帐号='A'
COMMIT TRAN

--接着马上使用第二连接执行下面的语句
SET TRANSACTioN ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN
SELECT 余额 FROM 帐户表 WHERE 帐号='A' 
COMMIT TRAN


我们会发现第二个连接的语句会立即返回,结果是103,但遗憾的是它读取的是脏数据。
如果我们把第二个连接的事务隔离级别设置为 READ COMMITTED、REPEATABLE READ 或者SERIALIZABLE,都可以避免“脏读”的发生。

(3)不一致的分析(非重复读)的再现
由表1可知,当事务的隔离级别为未提交读(READ UNCOMMITTED)或者READ COMMITTED的时候,便可在现此问题。
请测试下面这个例子(假设帐号A的余额为100):

--在第一个连接中执行以下语句

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
--或者 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN
SELECT 余额 FROM 帐户表 WHERE 帐号='A'
WAITFOR DELAY '00:00:10' --等待10秒
SELECT 余额 FROM 帐户表 WHERE 帐号='A'
COMMIT TRAN

--接着马上使用第二连接执行下面的语句
BEGIN TRAN
UPDATE 帐户表 SET 余额=10 WHERE 帐号='A'
COMMIT TRAN

我们会发现第一个连接中两次返回帐号A的余额不一样,第一次是100,第二次返回的是10,这是典型的“非重复读”问题。
如果把连接一的事务隔离级别设置为REPEATABLE READ 或者SERIALIZABLE,可防止此类问题。


(3)不一致的分析(非重复读)的再现
由表1可知,当事务的隔离级别为未提交读(READ UNCOMMITTED)或者READ COMMITTED的时候,便可在现此问题。
先看下面这个例子(假设帐号A的余额为100):

--在第一个连接中执行以下语句

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
--或者 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN
SELECT 余额 FROM 帐户表 WHERE 帐号='A'
WAITFOR DELAY '00:00:10' --等待10秒
SELECT 余额 FROM 帐户表 WHERE 帐号='A'
COMMIT TRAN

--接着马上使用第二连接执行下面的语句
BEGIN TRAN
UPDATE 帐户表 SET 余额=10 WHERE 帐号='A'
COMMIT TRAN

我们会发现第一个连接中两次返回帐号A的余额不一样,第一次是100,第二次返回的是10,这是典型的“非重复读”问题。

如果把连接一的事务隔离级别设置为REPEATABLE READ 或者SERIALIZABLE,可防止此类问题。

(4)幻像读的再现
由表1可知,当事务的隔离级别为READ UNCOMMITTED或者READ COMMITTED或者REPEATABLE READ的时候,便可再现此问题。
先看下面这个例子(假设帐号A的余额为100):

--在第一个连接中执行以下语句

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
--或者 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
--或者 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRAN
SELECT * FROM 帐户表 
WAITFOR DELAY '00:00:10' --等待10秒
SELECT * FROM 帐户表 
COMMIT TRAN

--接着马上使用第二连接执行下面的语句
BEGIN TRAN
INSERT INTO 帐户表 VALUES('C','300')
COMMIT TRAN

我们会发现第一个连接中在同一个事务中,同样的查询语句两次返回的结果集不一样,第二次返回的结果集中多了一条帐号为C的帐号,这是典型的“幻像读”问题。只有将连接一的事务隔离级别设置为SERIALIZABLE,才可防止此类问题。
  总结:为了避免事务并发带来的问题,可采用较高的事务隔离级别,但因此会降低事务的并行性;反过来如果追求高的并行性而使用较低的事务隔离级别,又容易带来并发的问题。因此SQL Server采用默认隔离级别是相对比较低的“READ COMMITTED”。在实际应用的时候,采用何种隔离级别视具体情况而定,也可以采用显式“上锁”的方法控制事务隔离级别,具体方法请留意笔者的相关文章。

关于“SQL Server中四类事务并发问题的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: SQL Server中四类事务并发问题的示例分析

本文链接: https://lsjlt.com/news/71581.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • SQL Server中四类事务并发问题的示例分析
    这篇文章将为大家详细讲解有关SQL Server中四类事务并发问题的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。SQL Server中四类事务并发问题的实例再现...
    99+
    2024-04-02
  • SQL Server中事务与锁的示例分析
    这篇文章将为大家详细讲解有关SQL Server中事务与锁的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一  概述在数据库方面,对于非DBA的程序员来...
    99+
    2024-04-02
  • MySQL事务的ACID特性及并发问题实例分析
    本篇内容主要讲解“MySQL事务的ACID特性及并发问题实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL事务的ACID特性及并发问题实例分析”吧...
    99+
    2024-04-02
  • sql server中内存的示例分析
    这篇文章将为大家详细讲解有关sql server中内存的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一. 前言 对于sql server 这个产品来说...
    99+
    2024-04-02
  • sql server中死锁排查的示例分析
    这篇文章主要介绍sql server中死锁排查的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!死锁的四个必要条件:互斥条件(Mutual exclusion):资源不能被共享...
    99+
    2024-04-02
  • SQL Server中WAITFOR DELAY注入的示例分析
    这篇文章主要为大家展示了“SQL Server中WAITFOR DELAY注入的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“SQL Server中WAITFOR DELAY注入的示例分...
    99+
    2023-06-04
  • SQL Server中的XML数据类型实例分析
    本篇内容主要讲解“SQL Server中的XML数据类型实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SQL Server中的XML数据类型实例分析”吧!SQL Se...
    99+
    2023-06-30
  • golang中并发和并行的示例分析
    这篇文章主要介绍了golang中并发和并行的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是golanggolang 是Google开发的一种静态强类型、编译型、...
    99+
    2023-06-15
  • sql server中错误日志errorlog的示例分析
    这篇文章将为大家详细讲解有关sql server中错误日志errorlog的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一 .概述SQL Server 将某些系...
    99+
    2024-04-02
  • java高并发中并发级别的示例分析
    这篇文章给大家分享的是有关java高并发中并发级别的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。阻塞一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用synchronized...
    99+
    2023-06-25
  • MySQL事务隔离实现并发控制的示例分析
    这篇文章主要介绍了MySQL事务隔离实现并发控制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、并发访问控制实现的并发访问的控制技术是基于锁;锁分为表级锁和行级锁...
    99+
    2023-06-20
  • pymysql解决sql注入问题的示例分析
    这篇文章将为大家详细讲解有关pymysql解决sql注入问题的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. SQL 注入SQL 注入是非常常见的一种网络攻击...
    99+
    2024-04-02
  • SQL Server中Table字典数据查询SQL的示例分析
    这篇文章主要介绍SQL Server中Table字典数据查询SQL的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言在数据库系统原理与设计(第3版)教科书中这样写道:数据库...
    99+
    2024-04-02
  • Java中并发容器的示例分析
    这篇文章给大家分享的是有关Java中并发容器的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、并发容器1.1 JDK 提供的并发容器总结JDK 提供的这些容器大部分在java.util.concurre...
    99+
    2023-06-15
  • React中并发功能的示例分析
    这篇文章将为大家详细讲解有关React中并发功能的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。React 是一个开源 JavaScript 库,开发人员使用它来创建基于 Web 和移动的应用程序...
    99+
    2023-06-20
  • Java中文问题的示例分析
    这篇文章将为大家详细讲解有关Java中文问题的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。我来说一下tomcat如何实现JSP的你就明白了。预备知识: 1.字节和unicode  Java内核是...
    99+
    2023-06-03
  • PHP开发安全问题的示例分析
    PHP开发安全问题的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。对于互联网应用的开发,作为开发者必须时刻牢记安全观念,并在开发的...
    99+
    2024-04-02
  • 一文分析SQL Server中事务使用的锁
    目录序SQL Server使用的锁及锁对象SQL Server执行Select时使用的锁SQL Server执行insert时使用的锁SQL Server执行update时使用的锁总结序 本文属于基础知识的回顾...
    99+
    2024-04-02
  • 一文分析SQL Server中事务使用的锁
    目录序SQL Server使用的锁及锁对象SQL Server执行Select时使用的锁SQL Server执行insert时使用的锁SQL Server执行update时...
    99+
    2024-04-02
  • SQL Server生成sql脚本并执行还原数据库的示例分析
    这篇文章将为大家详细讲解有关SQL Server生成sql脚本并执行还原数据库的示例分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。上次介绍过如何通过ba...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作