我们有一个SQL Server数据库表,其中包含用户ID,某些数值,例如余额和版本列。
我们有多个线程并行更新此表的值列,每个线程都在自己的事务和会话中(我们使用的是每线程会话模型)。由于我们希望发生所有逻辑事务,因此每个线程都会执行以下操作:
我们每个逻辑事务只执行一定次数,如果我们在X次尝试后无法提交,我们拒绝逻辑事务。
每个这样的线程周期性地提交,例如在100次成功的逻辑事务之后,将提交引发的I / O保持在可管理的级别。意思是 - 我们有一个具有多个刷新的单个数据库事务(每个事务),每次逻辑更改至少一次。
你问这里有什么问题?好吧,在提交时,我们看到对失败的逻辑对象的更改。 具体来说,如果我们通过步骤1(第一次)时值为50,并且我们尝试将其更新为100(但是我们失败了,因为例如另一个线程将其更改为70),则提交值50这一行。显然这是不正确的。
我们在这里缺少什么?
答案 0 :(得分:2)
好吧,我在这里没有太多的经验,但有一点我记得读in the documentation是因为如果发生异常,你应该立即回滚事务并处理会话。也许您的问题与会话处于不一致状态有关?
此外,在此处调用代码中的更新为not necessary。由于您在该会话中加载了该对象,因此它已被nhibernate跟踪。
答案 1 :(得分:1)
如果您想进行更改,为什么还要打扰行版本?如果你只是总是更新数据并让最后一笔交易获胜,那听起来你应该得到相同的结果。
至于更新成为永久更新的原因,它取决于版本检查/更新的SQL语句和事务控制的内容,这是您从代码示例中省略的。如果打开Hibernate SQL日志记录,很可能会发生这种情况。
答案 2 :(得分:0)
我不是一个nhibernate大师,但回答似乎很简单。
当nhibernate加载一个对象时,只要它在nhibernate会话缓存中就不希望它在db中改变。
如你所说 - 你有多线程应用程序。
这就是发生的事情=>
您缺少锁定机制。不能说明如何正确和优雅地应用它。也许Transaction
会有所帮助。
当我们同时使用nhibernate和raw ado.net时,我们遇到了类似的问题(幸运的是 - 仅用于查询 - 至少对于生产代码而言)。我们所要做的就是 - 在插入/更新时强制更新db,这样我们就可以通过全文搜索查询某些特定实体。
当我们使用原始ado.net重置db时,在集成测试中有StaleStateException
。 NHibernate会话通过大量测试活跃起来,但每次测试都试图在不了解NHibernate的情况下清理db。
答案 3 :(得分:0)