数据库更新锁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 项。