Linq to Sql : 并发冲突及处理策略

2023-10-27

0. 并发冲突的示例

    单用户的系统现在应该比较罕见了,一般系统都会有很多用户在同时进行操作;在多用户系统中,涉及到的一个普遍问题:当多个用户“同时”更新(修改或者删除)同一条记录时,该如何更新呢?
    下图展示了开放式并发冲突的一个示例:

并发冲突示例

    假设数据库中有一条记录Record{Field1=5, Field2=6, Field3=7}(以下简写为{5, 6, 7}),A、B两个用户按照如下顺序操作这一条记录:
(1). A读取该记录,取得的值为{5, 6, 7},读取完毕后,不对该记录加排他锁;
(2). B读取该记录,取得的值也为{5, 6, 7},读取完毕后,不对该记录加排他锁;
(3). B将该记录修改为{3, 5, 7},并写回数据库;由于该记录没有被其他用户锁定,且B在修改时该记录的值与第(2)步中读取的值一致,因此可以正常写入数据库;
(4). A将该记录修改为{5, 8, 9},并写回数据库;由于A在修改时该记录的值已更新为{3, 5, 7},与第(1)步中读取的值{5, 6, 7}不一致,因此引发并发冲突;

 

1. 开放式并发(乐观并发) & 封闭式并发(悲观并发)

     开始之前,先介绍两个概念(From 《SQL Server 2008联机丛书》)。

乐观并发控制

在乐观并发控制中,用户读取数据时不锁定数据。当一个用户更新数据时,系统将进行检查,查看该用户读取数据后其他用户是否又更改了该数据。如果其他用户更新了数据,将产生一个错误。一般情况下,收到错误信息的用户将回滚事务并重新开始。这种方法之所以称为乐观并发控制,是由于它主要在以下环境中使用:数据争用不大且偶尔回滚事务的成本低于读取数据时锁定数据的成本。

悲观并发控制

一个锁定系统,可以阻止用户以影响其他用户的方式修改数据。如果用户执行的操作导致应用了某个锁,只有这个锁的所有者释放该锁,其他用户才能执行与该锁冲突的操作。这种方法之所以称为悲观并发控制,是因为它主要用于数据争用激烈的环境中,以及发生并发冲突时用锁保护数据的成本低于回滚事务的成本的环境中

    举个例子来说:
    乐观并发:本文起始位置的图片,展示的是乐观并发情况下引发的冲突。
    悲观并发:继续沿用图片中示例的请求顺序,如果第(1)步中A读取这条记录后,给记录加上排他锁,并且一直持有,在更新完毕之前不释放该锁;则第(2)步中B尝试读取该记录时,请求会被阻塞,直到A释放该记录,或者请求超时。因此新的执行顺序(假设请求没有超时)为:A读取并锁定记录{5, 6, 7}-->B尝试读取该记录[B被阻塞等待]-->A写回{5, 8, 9}到数据库,并释放该记录-->B读取到{5, 8, 9},并锁定该记录-->B修改该记录并写回数据库……

 

2. Linq to SQL中的乐观并发控制

    L2S支持开放式并发控制。使用L2S执行修改和删除操作时,同时打开SQL Server Profile来查看生成的SQL代码,我们可以看到类似这样的代码(假设表上加了TimeStamp字段):

UPDATE TableName SET Field1=@p0, Field2=@p1 WHERE PrimaryKey=@p2 AND TimeStampField=@p3
//(省略)....
DELETE TableName WHERE PrimaryKey=@p0 AND TimeStampField=@p1
//(省略)....

    当记录被更新时,则其TimeStamp字段会被自动更新。因此,如果在用户读取该记录后、且更新该记录之前,有其他用户更新过这条记录,则更新会失败(根据受影响行数为0来判断),L2S会抛出ChangeConflictException异常。

    以上描述的是表上有加timeStamp字段的情况,如果表上没有TimeStamp字段,L2S会对映射为UpdateCheck = UpdateCheck.Always 或 UpdateCheck.WhenChanged的字段成员进行开放式并发检查,可以根据Sql server Profile来查看,不再赘述。

 

3. 冲突解决

    既然有了冲突,就需要把冲突给和谐掉。

    还是以本文起始位置的例子来说,最后A更新时,该更新为啥呢?可以存在如下三种选择:
(1). 覆盖数据值库:{5,8,9}?
(2). 保留数据库值:{3,5,7}?
(3). 合并为:{3,8,9}?

    这三种方式分别对了L2S的三种解决方案:

3.1 通过覆盖数据库值解决并发冲突

try
{
    db.SubmitChanges(); //需要指定为ConflictMode.ContinueOnConflict
}
catch (ChangeConflictException e)
{
 
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        occ.Resolve(); //保留当前值,覆盖数据库中的值
    }
}
db.SubmitChanges(ConflictMode.FailOnFirstConflict); //处理完冲突后,重试

3.2 通过保留数据库值解决并发冲突

try
{
    db.SubmitChanges();
}
catch (ChangeConflictException e)
{
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        occ.Resolve();//以数据库中的值,重写当前值
    }
}
db.SubmitChanges(ConflictMode.FailOnFirstConflict); //处理完冲突后,重试

3.3 通过与数据库值合并解决并发冲突

try
{
    db.SubmitChanges();
}
catch (ChangeConflictException e)
{
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        occ.Resolve();//保留数据库中的值和当前值,进行合并处理
     }
}
db.SubmitChanges(ConflictMode.FailOnFirstConflict); //处理完冲突后,重试

转载于:https://www.cnblogs.com/happyhippy/archive/2010/01/30/1660150.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linq to Sql : 并发冲突及处理策略 的相关文章

  • jenkins配置sonar并扫描C#代码

    背景 我的jenkins搭在linux上 1 下载插件 下载插件sonarqube scanner 用来集成sonarqube 在配置任务的时候才有sonarscanner的选项 2 全局工具配置 全局工具配置windows本地的msbui
  • qt系列-qt6在线安装慢的问题

    qt unified windows x64 online exe mirror https mirrors aliyun com qt 下载速度飞快

随机推荐

  • Qt贪吃蛇(代码裸写,不用creator)

    先上个图哇 图1 第一关视图 图2 第二关视图 游戏说明 1 每关只需吃20颗红果即可通关 2 增加新场景 在第二关出现 3 增加刚打开程序READY状态 按空格开始 4 增加暂停功能 在程序运行中按空格暂停 再按空格继续游戏 5 只要不关
  • Python客户端发布订阅MQTT云代理消息

    MQTT基础 MQTT 是一种开放且简单的客户端服务器发布 订阅消息传输协议 专为高延迟和低网络带宽环境下不同设备之间的机器对机器通信而设计 机器对机器通信 这很容易 一个系统需要与其他系统交换信息 在物联网环境中 设备之间的通信需求急剧增
  • react native 使用echarts做面积图

    react native 使用echarts 我用到了一个组件 react native secharts https github com shifeng1993 react native secharts 使用 import Echar
  • Git合并的代码 不提交服务器的方法

    使用Git下载代码的时候 常遇到合并的情况 然后再上传的时候 系统就会自动把合并代码的过程也上传 有时候会感觉非常的烦Merge remote tracking branch choose remote name master 每次先下载到
  • pycharm自定义多行注释的颜色

  • JWT续期问题,ChatGPT解决方案

    JWT JSON Web Token 通常是在用户登录后签发的 用于验证用户身份和授权 JWT 的有效期限 或称 过期时间 通常是一段时间 例如1小时 过期后用户需要重新登录以获取新的JWT 然而 在某些情况下 用户可能会在JWT到期之前使
  • DirectShow应用——支持Windows Media格式

    大家知道 微软定义了自己的一种媒体文件类型 叫做ASF Advanced Systems Format ASF其实是一个文件 容器 它本身并没有规定音视频的压缩格式 在ASF文件中 我们可以包含任何格式的压缩的 包括MPEG 4 或非压缩的
  • 抽象工厂设计模式的扩展

    american com itheima pattern factory config factory AmericanCoffee latte com itheima pattern factory config factory Latt
  • 【Apache Spark 】第 11 章使用 Apache Spark 管理、部署和扩展机器学习管道

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • git分支合并错误回滚

    1 合并 比如testB分支合并testA分支 2 还原 如果合并时 代码有错误 已经提交的远程分支 可以参考tortoisegit 还原到某个版本 强制还原 3 重新合并 可重新执行合并流程 改过错误代码后 重新提交的远程分支
  • Java异常类详解

    目录 异常简介 异常体系 异常的处理 自定义异常类 一 异常简介 1 1 异常定义 异常是运行程序的过程中产生的异常情况 异常的情况是指程序在运行过程中 可能由于外界条件的变更 不设想的不一致 导致出现错误的情况 如数据库连接 异常不同于常
  • C++类对象创建过程(分配空间、赋值和初始化、对象初始化顺序、虚函数表指针)

    http my oschina net alphajay blog 5029 from rss 初看到这个题目 你可能会有些疑惑 C 类对象的创建还有什么好说的 不就是调用构造函数么 实际上情况并不是想象中的那么简单 大量的细节被隐藏或者被
  • Node-RED中配置周期性执行、指定时间阶段执行、指定时间执行事件

    场景 Node RED简介与Windows上安装 启动和运行示例 Node RED简介与Windows上安装 启动和运行示例 霸道流氓气质的博客 CSDN博客 在inject节点可以设置重复触发的周期性事件 比如每两秒输出一次时间 注 博客
  • Windows系统服务器如何磁盘挂载

    桌面远程登录服务器后 服务器桌面上只有一个回收站的 我们在桌面空白处右键属性 gt 桌面 gt 自定义桌面 gt 然后把我的电脑前面的框框勾上 再然后点应用 确定 ok 回到桌面我们就能看到我的电脑了 步骤 点击我们电脑 gt 右键管理 g
  • VSCODE设置位置

    目录 设置位置 用户区 工作区 设置方法 设置编辑器 设置文件 结束 设置位置 VSCODE设置位置分为用户区和工作区 用户区 用户设置是全局的 对所有工作区和项目都有效 用户设置会存储在用户的配置文件夹中 并以settings json文
  • oceanbase 与hbase主要区别

    oceanbase支持跨表的事务 而hbase中支持跨行的事务 这是由他们的设计特别决定的 updateserver实际上是将Hbase所有ReginonServer的memtable聚合在一起 regionserver只服务一部分tabl
  • 编程tips

    一 是XOR 是不等于 if a b 和if a b 对对于聪明的编译器来说效率应该是一样的 二 与 的优先级比 高一级 表达式的结合次序取决于表达式中各种运算符的优先级 优先级从上到下依次递减 最上面具有最高的优先级 逗号操作符具有最低的
  • Spring中AOP

    1 概述 AOP 面向切面编程 将程序中的非业务代码抽取 在不修改业务代码的前提下 为其添加功能 功能增强 面向切面的编程思想底层是为目标创建一个代理对象 让代理对象调用目标类中方法 在代理对象调用时 可以额外的调用其他的方法 增强的方法
  • hduoj 2011

    多项式求和 Problem Description 多项式的描述如下 1 1 2 1 3 1 4 1 5 1 6 现在请你求出该多项式的前n项的和 Input 输入数据由2行组成 首先是一个正整数m m lt 100 表示测试实例的个数 第
  • Linq to Sql : 并发冲突及处理策略

    0 并发冲突的示例 单用户的系统现在应该比较罕见了 一般系统都会有很多用户在同时进行操作 在多用户系统中 涉及到的一个普遍问题 当多个用户 同时 更新 修改或者删除 同一条记录时 该如何更新呢 下图展示了开放式并发冲突的一个示例 假设数据库