NHibernate-悲观锁定不起作用
后续行动 正如我在上面的问题中所描述的,我正在尝试为并发问题实现悲观锁定(请随意添加)。但这对我不起作用 我做了一个非常简单的测试:我有两个独立的站点运行,它们都将计数器增加了500倍。我同时运行它们。最后,我希望我的表中的某一列的值,你猜是1000 这是代码。当然,它不是生产代码,但不管是否是测试代码,它都应该可以工作,对吗NHibernate-悲观锁定不起作用,nhibernate,concurrency,pessimistic-locking,Nhibernate,Concurrency,Pessimistic Locking,后续行动 正如我在上面的问题中所描述的,我正在尝试为并发问题实现悲观锁定(请随意添加)。但这对我不起作用 我做了一个非常简单的测试:我有两个独立的站点运行,它们都将计数器增加了500倍。我同时运行它们。最后,我希望我的表中的某一列的值,你猜是1000 这是代码。当然,它不是生产代码,但不管是否是测试代码,它都应该可以工作,对吗 for (int i = 0; i < 500; i++) { var tx = this.userRepo.Session.BeginTransaction(
for (int i = 0; i < 500; i++)
{
var tx = this.userRepo.Session.BeginTransaction();
var user = this.userRepo.GetById(42);
user.Counter++;
userRepo.Save(user);
tx.Commit();
}
现在,使用NHProfiler,我看到以下SQL语句:
从Id=42的“用户”中选择Id进行更新
但是结果是大约530,因此这大约是由于并发而丢失的更新的一半。我做错了什么?我在此测试中禁用了二级缓存。我是否使用了错误的锁定模式?我应该指定隔离级别吗?还有别的吗?提前谢谢
编辑:FluentNhibernate配置:
Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(connectionstring))
.Mappings(m => assemblyTypes.Select(t => t.Assembly).ToList().ForEach(a => m.FluentMappings.AddFromAssembly(a)))
.ExposeConfiguration(c => c.Properties.Add("hbm2ddl.keywords", "none"));
要使
LockMode.Upgrade
工作,所有事务都必须包含在事务中,因为LockMode.Upgrade
所做的是将其锁定到当前事务中
您的问题很可能是由于交易中没有包含对账单
乐观锁定不适用于单个语句,而是适用于相互分离的多个事务。例如:
Id=42
获取记录计数器
之后:
Id=42
获取记录计数器
没有更改,并处理更改的情况。使用悲观锁定,您可以确保在锁定所有必需记录的情况下,在单个事务中完成所有更改
B.t.w.:检查机制(同时,
计数器
是否发生了变化)可以由NHibernate自动处理。你能发布你的NHibernate配置代码吗?@upTheCraek:使用FluentNH,不确定你想看什么,但我在我的代码中包含了它-最后我使用BeginTransaction()和Commit()。这就是你的意思,对吧?抱歉,你是对的。序列化模式是什么(connection.isolation SessionFactory设置或BeginTransaction
的第一个参数)。有关其含义的更多信息,请参阅。试着玩这些游戏,看看这是否会带来不同。查看可序列化的会发生什么,因为这将保证它按预期工作。hmmm,可能使用for循环也会导致问题。似乎没有for循环,但使用Thread.Sleep导致并发,我使用IsolationLevel.RepeatableRead和LockMode.Upgrade确实获得了很好的结果。不过,如果您能澄清这些不同的机制和不同的类型是如何协同工作的,我们将不胜感激。我将不得不让您参考这些隔离级别的文档,因为在注释中处理这一点太多了:)。但是请注意,MSDN链接本身也有一些信息,但可能会提供更多信息。
Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(connectionstring))
.Mappings(m => assemblyTypes.Select(t => t.Assembly).ToList().ForEach(a => m.FluentMappings.AddFromAssembly(a)))
.ExposeConfiguration(c => c.Properties.Add("hbm2ddl.keywords", "none"));