数据库更新锁WITH UPDLOCK

今天因为并发的问题,又讨论了一遍。之前以为同时两个线程开启,线程A加了更新锁,线程B没有加,线程A更新后,线程B也会继续下去代码。但是今天测试了一下,原来线程A更新后(解锁),线程B将不会继续,会出现数据库语句出现修改之类的提示。

写法 SELECT * FROM TABLE WITH UPDLOCK WHERE ID=1

A代码段示例:

 using (TransactionScope trans = new TransactionScope())
                        {
                            using (var dbContext = new Qxun.Activity.DAL.ActivityDbContext())
                            {
string sqlStr = string.Format("SELECT * FROM TABLE WITH(UPDLOCK) WHERE ID={0} ", crossDomainPayRecord.ID);
                                VIPWeRegister046Play model = dbContext.Database.SqlQuery<VIPWeRegister046Play>(sqlStr).FirstOrDefault();
                            
                                if (Status == 0)//说明出现问题
                                {
                                    model.Status = Status;
                                    dbContext.Update<TABLE>(model);
                                    trans.Complete();
                                    return Content(res.ToXml());
                                }
                    trans.Complete();
                }
}                

B代码段示例 :

using (ActivityDbContext dbContext=new ActivityDbContext())
            {
                List<TABLE> model= dbContext.TABLE.ToList();
                foreach (var item in model)
                {
                    item.Status= 2;
            dbContext.Insert<Table>(new Table());
                    dbContext.Update<TABLE>(item);
                }
 List<Share> share = dbContext.Shares.ToList();
                if (share.Count == 0)
                {
                    dbContext.Insert<Share>(new Share());
                }
                share = dbContext.Shares.ToList();
                foreach (var item in share)
                {
                    item.MerchantWeixinUserID = 1;
                    dbContext.Update<Share>(item);
                }
            }

1.线程A进入更新锁代码段,线程B将会停止在dbContext.Update处,不会再继续下去(解锁操作两种:1.更新操作(非事务处理);2.事务处理结束(处于事务))

接下来有三种情况:

1.1线程A不进行更新操作(没有update操作,即使没有改变值),线程A结束事务后(解锁),线程B将继续运行

1.2线程A进行了更新操作,即此时Status状态值更改为0,线程B将会跳转入异常,异常详细上会有数据库信息更改之类的提示

1.3线程A一直停留在断点,不进行解锁操作,时间一旦达到限制,则线程B将会提示请求超时之类的(由于数据库请求是有设定时限的)

2.线程A未进入更新锁代码段,则线程B按照正常运行

3.线程A进入更新锁代码段时,线程B也可以使用select获取,即List<TABLE> model= dbContext.TABLE.ToList();这句会被执行的,直到update操作停止

4.一旦A线程进入更新锁代码,且进行了update操作,线程B中的插入更新dbContext.Insert<Table>(new Table()); dbContext.Update<TABLE>(item);这两句都不能执行,会出现报错。而share表相关的insert和update也不能运行,这是因为share的代码处理在TABLE下面,此时dbContext已是异常状态。如果将share放置到TABLE代码上方,则会正常运行或者是将share重新开启一个dbContext2进行操作。不过其中应该还有一些缘由...

5.一旦A线程进入更新锁代码,且未进行update操作,线程B中的插入dbContext.Insert<Table>(new Table());代码是会被执行的,且share相关的代码都会被执行。

异常提示:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。刷新 ObjectStateManager 项。

原文地址:https://www.cnblogs.com/danlis/p/8329116.html