NHibernate-悲观锁定不起作用

NHibernate-悲观锁定不起作用,nhibernate,concurrency,pessimistic-locking,Nhibernate,Concurrency,Pessimistic Locking,后续行动 正如我在上面的问题中所描述的,我正在尝试为并发问题实现悲观锁定(请随意添加)。但这对我不起作用 我做了一个非常简单的测试:我有两个独立的站点运行,它们都将计数器增加了500倍。我同时运行它们。最后,我希望我的表中的某一列的值,你猜是1000 这是代码。当然,它不是生产代码,但不管是否是测试代码,它都应该可以工作,对吗 for (int i = 0; i < 500; i++) { var tx = this.userRepo.Session.BeginTransaction(

后续行动

正如我在上面的问题中所描述的,我正在尝试为并发问题实现悲观锁定(请随意添加)。但这对我不起作用

我做了一个非常简单的测试:我有两个独立的站点运行,它们都将计数器增加了500倍。我同时运行它们。最后,我希望我的表中的某一列的值,你猜是1000

这是代码。当然,它不是生产代码,但不管是否是测试代码,它都应该可以工作,对吗

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
    获取记录

  • 检查计数器是否与第一笔交易中收到的值保持不变

    a。如果未更改,则使用增加的值更新计数器

    b。如果已更改,请处理更改的值

  • 结束交易

  • 乐观锁定意味着您“希望”两个事务之间的
    计数器
    没有更改,并处理更改的情况。使用悲观锁定,您可以确保在锁定所有必需记录的情况下,在单个事务中完成所有更改


    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"));