【问题标题】:Hibernate: force 'with (NOLOCK)' hint on all select queries, without changing isolation level休眠:在所有选择查询上强制“使用(NOLOCK)”提示,而不更改隔离级别
【发布时间】:2016-08-28 17:44:08
【问题描述】:

快速背景故事:

我正在处理一个非常旧的应用程序,该应用程序最近遇到了数据库锁定问题。该应用程序是用 Java 编写的并使用 Hibernate。我们发现的问题之一是事务的存活时间异常长,同时隔离级别也在 READ_COMMITED 和 READ_UNCOMMITED 之间频繁更改。虽然我们承认明确的解决方案是重构代码以使事务更小,但这将是一项我们目前无法完全承担的巨大工作(应用程序的大多数使用部分正在迁移到新系统,但此过程相对较慢)。

所以 - 因为我们对所有 Select 操作使用 READ_UNCOMMITED,而对其他所有操作使用 READ_COMMITED,一直在帮助我们的 DBA 确定了一种可能的解决方案,将隔离级别更改为全局 READ_COMMITED 并更改所有选择查询以包含提示'与(NOLOCK)'。他说,从功能上讲,检索数据的方式应该没有区别(因为我们现在使用脏读没有问题),同时为我们提供了不必频繁更改事务中的隔离级别的优势。我相信他的想法也适用于我们最近收到的关于由隔离级别更改引起的数据库锁的报告。

所以 - 我们可以(如果可以,如何?)告诉 hibernate 为所有使用映射的 java 对象和 HQL 自动生成的查询添加一个“with (nolock)”提示(甚至可能传递现有的 SQL休眠,虽然这似乎是在推动它 :) ) 而不改变隔离级别?

最后的附注:我们使用的是旧版本的 hibernate,v3.5,现在升级不太可能,一些非常“聪明”的人决定在某个时候对其进行污染,插入一些他们自己的应用程序代码用途。升级已尝试多次,但都失败了。

另外:我已经检查了很多相关的线程,总体思路似乎是:不要使用 nolock,更改隔离级别,如前所述,我们不打算这样做。

Edit1:由于应用程序在过去 12 年中不断开发,有很多模块甚至没有被当前的开发团队浏览过,理想的解决方案是不需要识别使用持久对象的每一位 Java 代码。

Edit2:解决此问题的一种可能方法 - 如果 Hibernate 允许它 - 将添加一种拦截器形式,该拦截器在传递给数据库驱动程序之前接收格式化的 SQL 查询。然后我会自己添加提示,使用某种形式的正则表达式。

非常感谢您。

【问题讨论】:

    标签: java sql-server hibernate isolation-level nolock


    【解决方案1】:

    您不能将 (NOLOCK) 与 HQL 一起使用。但是,如果您决定更改查询,则可以使用本机 SQL。比如:

    getCurrentSession().createSQLQuery("select * from table with(NOLOCK)").list();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 2019-12-13
      相关资源
      最近更新 更多