如何修复&避免:行被另一个事务更新或删除(或未保存的值映射不正确)

时间:2014-09-27 03:58:07

标签: hibernate grails

我正在使用jMeter对我的grails应用程序进行性能测试。在并发用户访问该站点的情况下,有时我在日志中看到以下错误:

  

Excepton:行被另一个事务更新或删除(或   unsaved-value mapping不正确)[com.mypack.app.MyClass#1113]

如何在未来修复并避免这些错误?

以下是完整堆栈:

->>  245 | doCall    in com.mypack.app.MyController$_save_closure3_closure8
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    225 | save      in com.mypack.app.MyClontroller
|    195 | doFilter  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter  in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run . . . in java.lang.Thread

1 个答案:

答案 0 :(得分:2)

Grails默认为乐观锁定,它假定并发更新很少或没有,或者当它们发生时,您有适当的策略来解决问题。这与许多源控制系统类似,其中两个用户可以编辑一个文件,但如果编辑重叠则存在必须手动解决的冲突。

通常,解决并发编辑问题是不切实际的。如果您在MyClass实例中更改了一个属性并且我更改了另一个属性,理论上我们可以将这两个更改合并为一个新记录,但是如果您的更改会影响我在看到它时所做的更改会怎么样?第一λ

为了简单起见,如果您允许同时进行修改并且没有合并'策略,你应该使用显式锁定。这确实会影响性能,但如果您只锁定特定的域类或特定的工作流,则影响应该很小,特别是如果记录保持锁定的时间很短。

但是锁定网络应用程序很棘手。当你开始编辑'时需要锁定。工作流并加载域类实例以填充该GSP,并在用户在浏览器中进行更改时保持记录锁定,并在“更新”时释放锁定。行动结束(成功与否)。 Grails不支持此功能,因为每个请求都有自己的Hibernate Session并且在每个请求结束时关闭它(以及它会释放锁定的Connection) 。如果你要实现这一点,你必须确保如果没有调用更新操作(或在最大允许时间之后调用),则释放锁以允许其他人编辑。

因此,您要回到手动合并策略(或Webflow或类似的东西)。您可以通过在version false块中添加mapping来删除域类中的自动版本检查。然后在您的更新操作中,将检查过时版本的块转换为查看版本但也更改字段的自定义代码,并使用对您的域类有意义的任何逻辑来解析/合并并发编辑。