oracle数据库并发问题请教 返回

SqlSugar
24 163

这种情况下 更新第二个数据会把第一个数据清空掉  并发也会出现此问题 

image.png

Update 封装的

image.png


image.png

热忱回答24

  • 第一个图已修正image.png

    0 回复
  • 你2条记录的主键都一样的当然会更新第一条

    0 回复
  • @fate sta:有什么方式避免吗 如果是并发的话 出现这个问题就很麻烦 我测试的EF是这两个都更新上了 不是覆盖

    0 回复
  • https://www.donet5.com/Home/Doc?typeId=2399

    0 回复
  • 有并发控制

    0 回复
  • @fate sta:这种情况是不是SetColumns的更新是不是也可以避免

    0 回复
  • @许莫弃。J:只更新一列可以用setcolums 

    0 回复
  • 你这个是逻辑问题 更新2的时候用date1.Time.AddDays不就行了

    0 回复
  • 这个update方法,可能翻译成sql是整条数据更新,包括本次操作没改过的数据,依然赋值原值。这种操作在多进程并发操作一条数据更改不同字段时,会产生不必要的脏数据,导致数据错误。如果每次对实体的单个字段更新,都变成使用setcolums的方式,我个人认为已经失去ORM本身的意义,代码变得很繁琐。不知道有什么好的解决方案?

    0 回复
  • @fate sta:这个update方法,可能翻译成sql是整条数据更新,包括本次操作没改过的数据,依然赋值原值。这种操作在多进程并发操作一条数据更改不同字段时,会产生不必要的脏数据,导致数据错误。如果每次对实体的单个字段更新,都变成使用setcolums的方式,我个人认为已经失去ORM本身的意义,代码变得很繁琐。不知道有什么好的解决方案?

    0 回复
  • @曾几何时https://www.donet5.com/Home/Doc?typeId=2399 这个不给了方案吗?

    0 回复
  • 更新并发基本乐观锁控制 

    0 回复
  • 单个字段的更新本来就是 setcolums最方便 ,整个对象更新才用实体

    0 回复
  • @fate sta:论坛的说明文档里关于更新和进程并发的内容,我已经全部看过了。我们从EF切换来SqlSuger。发现EF和SqlSuger对于更新的处理差异很大。特别是事务、并发等。EF中基于更改的字段做实体更新,不会出现多进程同时更新同一条数据不同字段时被覆盖的情况。不同进程更新同一条数据不同字段时,即使使用原生sql语句并发也不会报错。我们现在做的系统与硬件交互频繁,基于大量实体的状态和硬件状态做逻辑处理,根据不同分支更新不同数据,多进程,并且通过业务逻辑实现多进程不会更新同条数据同一字段,会同时更新同一条数据的不同字段。但是现在 1、希望用已经查询出的实体直接赋值更新的方式,setcolums的方式重复写查询。2、只更新希望更新的字段,非全字段更新(多进程脏数据导致数据错误)3、多进程同时更新不同字段不希望通过校验时间戳抛异常。因为①不合理。②抛了异常后自动化过程被终止,并发的越频繁,抛异常的次数越多,系统无法交付。

    我始终有一个难以理解问题,为什么SqlSuger的设计,对于实体的更新要采用全字段更新数据库的模式?这种模式在我软件开发生涯中从来没有用过。想不通为什么要将没有变化的值再次赋予旧值更新数据库。这样不会产生不必要的脏数据吗?对于实体的灵活操作本来是ORM框架的亮点,用过SqlSuger的其他同事也同样为这个功能感到惊讶。

    以上仅是技术研讨,并非有其他意思,望回复交流。

    0 回复
  • @曾几何时:你上面的例子并不能很好的让我明白你的意图,你只写了个同步方法,并不能模拟你需要的场景, sqlsugar更接近ADO处理 想生成什么样的SQL就生成什么样的SQL和EFCORE设计上还是很大区别 ,只是处理方不同 ,可能更底层一些

    0 回复
  • var result= db.Updateable<Student>()
    .SetColumns(it => it.Num == it.Num+1) 
    .Where(it => it.Id == 1)
    .ExecuteCommand(); //只更新一个字段这样写就行了


    0 回复
  • image.png这个图片中,data2跑完之后,data1更新的unbindtime字段已经不再是它当时更新的时间字段了。data2在更新BindTime字段时,也将data1中的unBundTime字段也更新了。这种情况不是合理的。合理的情况是data1只更新unbindTime字段的值,data2更新BindTime字段的值。这个例子将data1和data2放在不同的进程里,就是我们现在的困扰。

    我们的系统现在存在大量并发的这种更新。但既然使用了ORM框架,就想用对实体的直接操作的方式,简单明了,不想用setcolums的方式。更不想因为这个再抛异常。简单的说,我们希望用更新实体的方式,多进程各自更新各自的字段,不覆盖。

    0 回复
  • @fate sta:我们更新字段的方式,大约像这样,Model A,B,C。。。硬件类 M1,M2,M3。if(A.a1&&B.b1&&M1.x&&M3.x){A.a2=xxx;B.b2=XXXX......}else if{.....}。最后保存实体类。要通过好多单个的实体跟其他硬件设备信号做联合判断,再处理其他的业务,然后可能要更新参与判断的单个实体的其他字段。

    0 回复
  • @曾几何时:不清楚你的具体需求,提供一个可让我看懂的例子,上面方法只是一个同步,完全可以你自个控制逻辑,或者你用多线程模拟一个场景代码

    0 回复
  • 没有efcore ,那其他用dapper ado 就不能用了吗? 我认为你应该转变一下思路, 你把EFCORE定位习惯了,不习惯其他的思维去处理数据

    0 回复
  • 至于你说的if else 逻辑sqlsugar很好实现

                var updateable = db.Updateable<Order>();
                if (条件1)
                {
                    updateable.SetColumns(it => new Order() { Name = "a", CreateTime = DateTime.Now });//更新2列
                }
                else
                {
                    updateable.SetColumns(it => new Order() { Name = "a1" });//更新一列
                }
                updateable.Where(it=>it.xx=1).ExecuteCommand();


    0 回复
  • @fate sta:条件1里面已经用到了你要更新的Order对象,还有其他实体对象和硬件信号。所以我们都是直接查出实体,在if里面联合硬件信息判断,最后在if方法体里更新。我们做的项目是自动化项目,增删改,大多是后台服务自动完成。不是网站靠人去点击,表单类的项目。

    0 回复
  • @曾几何时:提供具体用例吧,这个东西讲不清楚的 

    0 回复
  • 你的例子 同一个对象更新2次 这个一点意义没有,同一个对象为什么更新2次 ,更新一次不就行了,提供一些比较实在的例子

    0 回复