Hibernate使用hibernate.jdbc.batch_versioned_data保存过时的数据 [英] Hibernate saves stale data with hibernate.jdbc.batch_versioned_data

查看:1427
本文介绍了Hibernate使用hibernate.jdbc.batch_versioned_data保存过时的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



Hibernate 4.2


ojdbc6 - Oracle 11.2.0.3。 0 JDBC 4.0

Oracle数据库11g



问题



我们遵循了许多建议,以如下方式配置Hibernate批处理:

 <属性NAME = hibernate.jdbc.batch_size > 100℃; /性> 
< property name =hibernate.order_inserts> true< / property>
< property name =hibernate.order_updates> true< / property>
< property name =hibernate.jdbc.batch_versioned_data> true< / property>

我们检查了日志,我们看到生成的SQL语句被批量处理。但是,如果两个事务同时修改相同的版本化实体行,Hibernate将成功提交它们两个,导致丢失最后提交的事务中的冲突更新(两个事务中保存非冲突数据,因此最后一个事务离开数据库在不一致的状态)。



令人惊讶的是,这种行为很少有文档。 Hibernate官方文档说:
$ b


hibernate.jdbc.batch_versioned_data



将此属性设置为true if您的
JDBC驱动程序会从executeBatch()中返回正确的行数。打开此选项通常是安全的
。然后Hibernate将使用批量
DML自动版本化数据。默认为false。


通常安全?我们几乎将这个版本发送到了生产环境中,然后才注意到整个版本都被破坏了。



我们搜索了一个博客在五年前发布,描述了这种古怪;显然Hibernate在很长一段时间内对此没有做任何事情。



Hibernate的行为是否有这样的原因?它从jdbc驱动程序获取更新行数未知的信息,为什么它不会抛出异常来表明它,而是留下版本检查已成功传递的印象?

oracle驱动程序应该返回正确的行数。如果情况并非如此,我会感到惊讶。你能否确认司机的结果是正确的?
您可以打开Hibernate日志记录来检查它。



几件事情要检查:


  1. 记录发送到数据库的实际SQL,并检查版本列是否在where子句中提及。不知道Hibernate是否通过批处理记录了SQL,您可能不得不采取不同的方式记录SQL(例如,p6spy)。

  2. 如果在并发更新期间行计数正确返回,那么应用程序工作正常。通过检查版本栏的值是否更新得到更正来确认这一点。
    根据以下链接,这个问题已经在Oracle驱动程序中出现,直到11g,并在12c版本中修复。


    https://hibernate.atlassian.net/browse/HHH-3360



    <对于之前的Oracle版本,有一些额外的信息应该是有用的,即提供定制解决方案。



    其他资源:
    https://hibernate.atlassian.net/browse/HHH-5070


    Environment

    Hibernate 4.2

    ojdbc6 - Oracle 11.2.0.3.0 JDBC 4.0

    Oracle Database 11g

    The issue

    We followed many recommendations to configure our Hibernate batching the following way:

    <property name="hibernate.jdbc.batch_size">100</property>
    <property name="hibernate.order_inserts">true</property>
    <property name="hibernate.order_updates">true</property>
    <property name="hibernate.jdbc.batch_versioned_data">true</property>
    

    We checked our logs, and we saw that generated SQL statements are batched. However, if two transactions modify the same versioned entity rows concurrently, Hibernate will successfully commit both of them, resulting in loosing conflicting updates in the transaction that committed last (non-conflicting data are saved in both transactions, thus the last transaction leaves the database in an inconsistent state).

    Surprisingly, there is very little documentation on this behavior. Hibernate official documentation says:

    hibernate.jdbc.batch_versioned_data

    Set this property to true if your JDBC driver returns correct row counts from executeBatch(). It is usually safe to turn this option on. Hibernate will then use batched DML for automatically versioned data. Defaults to false.

    Usually safe? We almost sent this to production before noticing that the entire versioning is broken.

    We googled out a blog posted five years ago that describes this weirdness; apparently Hibernate has not done anything regarding this for a long time.

    Is there any reason why Hibernate behaves like this? It gets the information from the jdbc driver that the count of updated rows is unknown, why does it not throw an exception to indicate it, but rather leaves the impression that version check has passed successfully?

    解决方案

    The oracle driver should return correct row counts. I will be surprised if this is not the case. Were you able to confirm that the results from the driver is correct? You can turn on Hibernate logging to check this.

    Couple of things to check:

    1. Log the actual SQL being sent to the DB and check to see that the version column is mentioned in the where clause. Not sure if the SQLs are logged by Hibernate logging with batching on, you might have to resort to a different way of logging the SQLs then (e.g., p6spy)

    2. If the row counts are being returned correctly during concurrent updates, then the application is working fine. Confirm this by checking that the values of the version column is updated corrected.

    Update According to the following link, this issue has been present with the Oracle driver until 11g and fixed in version 12c

    https://hibernate.atlassian.net/browse/HHH-3360

    For prior Oracle versions there is some additional information that should be useful, i.e., a custom solution is provided.

    Additional resources: https://hibernate.atlassian.net/browse/HHH-5070

    这篇关于Hibernate使用hibernate.jdbc.batch_versioned_data保存过时的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆