Java Oracle在提交和选择之间存在延迟
我们有一个Java工作流应用程序,它使用Oracle数据库跟踪其步骤以及与其他服务的交互。在工作流运行期间,会执行多个插入/更新/选择,有时选择不会返回更新的数据,即使插入/更新提交在成功完成之前已运行。工作流出错后(由于数据不正确),如果我们返回并通过第三方应用程序检查数据库,则会显示新的/更新的数据。在我们的承诺完成和可见之间似乎有一个延迟。这种情况大约发生在所有工作流运行的2%中,并且在大量使用数据库时会增加 我们的数据库支持团队建议将参数max commit propagation delay更改为0,因为它默认为700。这似乎是一个可能的解决方案,但最终并没有解决我们的问题 应用程序在WebSphere上运行,Oracle数据库配置为JDBC数据源。我们正在使用Oracle 10.1g。应用程序是用Java1.5编写的 任何帮助都将不胜感激 编辑:示例代码Java Oracle在提交和选择之间存在延迟,java,sql,database,oracle,websphere,Java,Sql,Database,Oracle,Websphere,我们有一个Java工作流应用程序,它使用Oracle数据库跟踪其步骤以及与其他服务的交互。在工作流运行期间,会执行多个插入/更新/选择,有时选择不会返回更新的数据,即使插入/更新提交在成功完成之前已运行。工作流出错后(由于数据不正确),如果我们返回并通过第三方应用程序检查数据库,则会显示新的/更新的数据。在我们的承诺完成和可见之间似乎有一个延迟。这种情况大约发生在所有工作流运行的2%中,并且在大量使用数据库时会增加 我们的数据库支持团队建议将参数max commit propagation de
DataSource ds; // spring configured
String sql = "INSERT INTO " + currentTable + " (" + stepId + ',' + stepEntryId + ", " + stepStepId + ", " + stepActionId + ", " + stepOwner + ", " + stepStartDate + ", " + stepDueDate + ", " + stepFinishDate + ", " + stepStatus + ", " + stepCaller + " ) VALUES (?, ?, ?, null, ?, ?, ?, null, ?, null)";
Connection conn = ds.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
// set values
stmt.executeUpdate();
// close connections
// later on in the code...
Connection conn = ds.getConnection();
PreparedStatement stmt = null;
ResultSet rset = null;
String sql = "SELECT " + stepId + ", " + stepStepId + ", " + stepActionId + ", " + stepOwner + ", " + stepStartDate + ", " + stepDueDate + ", " + stepFinishDate + ", " + stepStatus + ", " + stepCaller + " FROM " + currentTable + " WHERE " + stepEntryId + " = ?";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, entryId);
rset = stmt.executeQuery();
//close connections
你在使用ORM吗?它可能是从缓存中选择,而不是在更改后形成数据库。默认情况下,您描述的行为应该是不可能的-在提交的事务中所做的更改将立即对所有会话可用。但是,也有例外情况:
如果您无法控制或查看数据源类的行为,您可能希望尝试对新获取的连接执行回滚,以确保它没有已建立的延迟事务。如果DBA团队试图修改
max\u commit\u propagation\u delay
参数,这可能意味着您正在连接到一个RAC实例(即:多个不同的服务器访问一个数据库)
在这种情况下,当您在java代码中关闭并重新打开连接时,可能会有其他服务器响应您的请求。延迟参数意味着当两个实例不在完全相同的时间点时,存在一个小的时间范围。您得到的答案与某个时间点一致,但可能不是最新的
正如KM所建议的,最简单的解决方案是在提交后保持连接打开
或者,如果可行的话,您也可以在关闭连接后添加延迟(例如,如果这是一个批处理作业,响应时间并不关键)。这听起来像是RAC的问题,连接到两个不同的实例,并且SCN不同步
作为解决方案,考虑不要关闭数据库连接并获得新的连接,但重用相同的连接。
如果这不可行,则向查询中添加一次重试,尝试检索插入的行。如果未返回该行,请稍睡片刻,然后重试查询。将其放入一个循环,在指定的重试次数后,您可能会失败 [增编] 史蒂夫·布罗伯格(Steve Broberg(+1!)在他的回答中提出了一些有趣的想法。我没有考虑:
可能不是立即等待COMMIT
- 事务隔离级别可以是除读提交之外的任何级别
我确实考虑过闪回查询的可能性,并且没有提到它就把它驳回了,因为OP没有明显的理由使用闪回查询,也没有证据表明代码片段中有这样的事情。
[/address]一种可能的解决方法可能是使用JTA事务。 它通过多个打开/关闭的jdbc连接保持“幕后”连接打开。也许它会让你的连接保持在同一台服务器上,避免这个同步问题
UserTransaction transaction = (UserTransaction)new InitialContext().lookup("java:comp/UserTransaction");
transaction.begin();
// doing multiple open/close cxs
transaction.commit();
代码片段实际上没有包含提交 如果您假设/依赖于执行提交的关闭连接,那么它可能不是同步的(即java可能会在通知Oracle关闭连接时报告连接已关闭,这意味着可能是在提交完成之前)