【发布时间】:2020-11-15 04:52:37
【问题描述】:
在我的数据库中处理并发:
- 客户端 A 更新一行
- 客户端 B 尝试更新同一行
- 客户端 B 需要等待客户端 A 提交他的更新
客户端 A 和 B 实例都被模拟并使用此代码:
using (myEntities db = new myEntities ())
{
db.Database.Connection.Open();
try
{
using (var scope = db .Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
{
var test = db.customer_table.Where(x => x.id == 38).FirstOrDefault();
test.bank_holder_name = "CLIENT NAME XXXX";
db.SaveChanges(); <=== CLIENT B stop here while client A still in progress. After CLIENT A finish commit, here will throw *Deadlock found error*"
scope.Commit();
}
}
}
catch (Exception ex)
{
throw;
}
}
这不是我所期望的 Client B 应该等待并且不允许查询有关行 id=38 的任何数据,但不知何故它可以继续直到 SaveChanges 并最终抛出错误.
因此,我怀疑这可能是由 linq(不正确的行/表锁)引起的
我编辑了我的代码如下:
using (myEntities db = new myEntities ())
{
db.Database.Connection.Open();
try
{
using (var scope = db .Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
{
var test = db.Database.ExecuteSqlCommand("Update customer_table set bank_holder_name = 'CLIENT XXXXX' where pu_id = 38"); <===== Client B is stop here and proceed after Client A is completed
db.SaveChanges();
scope.Commit();
}
}
}
catch (Exception ex)
{
throw;
}
}
最后,事务正在使用上面的代码(不是 linq 函数)。这太令人困惑了,linq 在使 Transaction 工作不一致的行为背后做了什么?
【问题讨论】:
-
隔离级别没有定义/规定锁定时刻。这是事务逻辑行为的指示:sqlperformance.com/2014/04/t-sql-queries/…。
-
并且在 SQL Server 中 SERIALIZABLE 允许并发读取行,但通过使一个事务失败并出现死锁来防止冲突更新。
-
好吧,看来我完全误解了 SQL Server 中的事务隔离。如果是这种情况,我们如何处理 EF 中上述情况的并发?我相信常见的解决方案是使用悲观锁,但 EF 不支持这个....
标签: sql entity-framework linq isolation pessimistic-locking