我正在开发一个大型应用程序,用很多数据管理复杂的“事件”。
应用程序被分解为客户端(C#主要是.NET 2.0),基于WCF的服务器在IIS上运行(此层的Web服务),数据后端是基于MS SQL Server的NHibernate数据库后端。
我们遇到了以下情况的错误:
多个用户(在本例中为6,在我们的测试中)同时在客户端上保存持久对象(例如事件)。 (这是通过口头倒计时完成的,所以我们说的是由于反应时间而产生的第二个差异)
当客户端保存对象时,客户端会调用服务器来保存该对象。服务器执行所需的任何业务逻辑,然后通过NHibernate提交更改。
在这种情况下(多次保存服务调用),一些客户端将返回一个无法处理的异常:
“行已被其他交易更新或删除”
这是NHibernate的例外。
在我的研究中,我发现了一些此错误的实例,但它始终是顺序的。我们的应用顺序很好,只有同时保存才会发生。
如何同时保护多个同时进行的NHibernate事务?
(这将是一个高容量的应用程序,所以最小的需要锁定是好的。我们不能一般锁定所有保存。)
是否有NHibernate设置会这样做?我们需要先弄清楚一些服务器代码侧锁吗?数据库是否可以使用不同的事务保护设置来处理它?</ p>
与大多数线程问题一样,这是一个测试的熊,因此研究/理论方法。这样的架构有什么经验?
编辑:更多信息和理论。
似乎更改直接在表中作为主要实体的值不会导致此问题,同时更改通过连接访问的元素。 (在这种情况下是一组属性)。
我们的工作理论似乎适合这种情况如下:
同一事件有多个保存。每个人都获得现有事件的副本(进行修改)。第一个要保存的是好的。然而,后者有更新,例如添加或删除属性(这是一个连接表),并发现需要完成的添加或删除已经完成,并因为另一个事务编辑了事件而退出。
我们应该如何保持这些事件的同步?
答案 0 :(得分:1)
我遇到了与多线程的单个用户应用程序相同的问题。关键是用[ThreadSafe]装饰我的会话变量。奇怪的是,我所看到的各种会话管理员似乎并没有这样做,他们认为它们是自动线程安全的......根据我的经验不是这样。
答案 1 :(得分:1)
我接受了上述答案,因为它或多或少是我们选择的路线。我想进一步阐述。我们的应用程序旨在大量使用,因此完全锁定“更新主要实体”程序是一个坏主意。
我们最终做的是使用C#互斥锁,它使用“一些独特的东西”来锁定,在这种情况下是一个事件ID。这意味着对同一复杂实体的任何操作都将被锁定,并在这种意义上变为“原子”。这解决了我们的问题。我们或多或少地(通过现有的实用程序类)将每个“破坏性”服务操作包含在互斥锁中。