0

快速背景故事:

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

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

那么-我们可以(如果可以,如何?)告诉hibernate在所有使用映射的java对象和HQL(甚至可能将现有的SQL传递给hibernate)自动生成的查询上添加一个'with(nolock)'提示,虽然这看起来像是在推动它:)))而不改变隔离级别?

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

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

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

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

非常感谢您提前。

4

1 回答 1

0

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

getCurrentSession().createSQLQuery("select * from table with(NOLOCK)").list();
于 2016-05-03T18:29:26.840 回答