是否可以在Hibernate中执行COMMIT WRITE BATCH NOWAIT?
答案 0 :(得分:2)
我没有广泛搜索,但我找不到任何证据表明您可以在JDBC驱动程序级别访问此功能。
这使您可以选择在实例或会话级别指定COMMIT_WRITE
参数,如果这对您有意义的话。
为了以防万一,让我引用这篇博客文章(我将内容粘贴参考,因为原始网站不可用或已死,我不得不使用Google缓存):
Using "Commit Write Batch Nowait" from within JDBC
任何使用过新版本的人 Oracle的异步提交功能 10.2将意识到它对事务处理非常有用 传统上的系统 受
log_file_sync
等待事件限制。
COMMIT WRITE BATCH NOWAIT
更快 因为它不等待消息 确保交易是 安全地在重做日志中 - 而不是它 假设它会成功。这几乎 消除了log_file_sync
个事件。它 也可以说会破坏整体 提交的目的,但有很多 丢失的情况 特定交易(比如删除 完成的会议)是完美的 生存下来,更可取 而不是无法接受传入 请求,因为你所有的连接 忙着log_file_sync
等待 事件任何使用Oracle JDBC的问题 驱动程序是10.2或者 11.1驱动程序具有允许您访问此功能的任何扩展 很容易 - 虽然Oracle有很多 所有供应商特定扩展 各种各样的东西支持异步 提交失踪。
这意味着你可以:
通过搞乱来打开实例级别的异步提交
COMMIT_WRITE
init.ora
参数。 这将是一个非常好的机会 让你解雇,因为整个过程 整个系统COMMIT将是 异步。虽然我们认为这是 那里的生产系统疯狂 是设置它的时间 开发盒很有意义,就像你一样 是80%日志文件同步绑定设置COMMIT_WRITE
以COMMIT WRITE BATCH NOWAIT会让你看到什么 如果你能以某种方式,你面临的问题 修复你当前的那些。在会话级别更改
COMMIT_WRITE
。这并不像以前那样危险 在系统范围内做,但很难 看到它对现实世界是可行的 系统与人们关心的交易 约。准备并使用“BEGIN COMMIT WRITE BATCH NOWAIT”的PL / SQL块; 结束“。这比第一个更安全 两个想法,但仍然涉及一个网络 往返。
使用异步提交将您的语句包装在匿名块中。 这是我们见过的最好的方法。 你的代码看起来像 这样:
BEGIN -- insert into generic_table (a_col, another_col, yet_another_col) values (?,?,?); -- COMMIT WRITE BATCH NOWAIT; -- END;
答案 1 :(得分:0)
我一直在寻找一种方法来做到这一点但却无法让它在测试中发挥作用。我坚持的原因是我期待我的测试得出错误的结果。我通过手动获取共享表锁来模拟添加索引进行测试 - 但在这种情况下,insert
查询获取锁,而不是commit
。所以它实际上并没有解决我想要解决的问题。我通过将这些插入移动到后台队列来解决我的问题,因此它们不会阻止主Web请求。
无论如何,我认为你仍然可以在Hibernate中进行异步提交。基本上,您可以使用Session.doWork()
方法来访问本机Connection
对象(或者在旧版本的Hibernate中使用Session.connection()
方法)。我还将提交SQL移动到策略接口中,以便我们可以运行基于HSQLDB的测试,这些测试无法理解Oracle特定的SQL。
事实上,使用Session.createSQLQuery
并提供SQL可能没问题,避免直接使用Connection
。试一试,看看它是如何运作的。
private NativeStrategy nativeStrategy = new OracleStrategy();
interface NativeStrategy {
String commit();
}
public static final class OracleStrategy implements NativeStrategy {
public String commit() {
return "COMMIT WRITE BATCH NOWAIT";
}
}
public void saveAsynchronously(MyItem item) {
session.save(item);
session.flush();
// Try to issue an asynchronous commit where supported.
session.doWork(new Work() {
public void execute(Connection connection) throws SQLException {
Statement commit = connection.createStatement();
try {
commit.execute( nativeStrategy.commit() );
} finally {
commit.close();
}
}
});
}