And*_*rew 8 java sql database oracle websphere
我们有一个Java工作流应用程序,它使用Oracle数据库来跟踪其步骤以及与其他服务的交互.在工作流运行期间,执行几次插入/更新/选择,有时候select不会返回更新的数据,即使在成功完成之前运行的插入/更新提交也是如此.在工作流出错后(由于数据不良),如果我们返回并通过第三方应用程序检查数据库,则会显示新的/更新的数据.在我们的提交通过和可见之间似乎存在滞后.这种情况大约占所有工作流运行的2%,并且在数据库使用量很大时会增加.
我们的数据库支持团队建议将参数max-commit-propagation-delay更改为0,因为它默认为700.这似乎是一个可能的解决方案但最终没有解决我们的问题.
应用程序在WebSphere上运行,Oracle数据库配置为JDBC数据源.我们使用的是Oracle 10.1g.该应用程序是用Java 1.5编写的.
任何帮助,将不胜感激.
编辑:示例代码
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
Run Code Online (Sandbox Code Playgroud)
默认情况下,您描述的行为应该是不可能的 - 在已提交的事务中进行的更改将立即对所有会话可用.但是,也有例外:
您是否在COMMIT命令中使用任何WRITE选项?如果不是,请确认COMMIT_WRITE初始化参数的值.如果要么使用"WRITE BATCH"或特别是"WRITE BATCH NOWAIT",那么您可能会遇到并发问题."WRITE BATCH NOWAIT"通常用于写入事务的速度比可能的并发问题更重要的情况.如果初始化参数使用"WRITE"变体,则可以通过在提交中指定IMMEDIATE子句来基于事务覆盖它(请参阅COMMIT)
试图在另一个事务提交之前读取调用SET TRANSACTION的数据的事务是什么?使用SET TRANSACTION指定SERIALIZATION LEVEL READ ONLY或SERIALIZABLE将导致事务看不到在调用SET TRANSACTION之后发生的其他已提交会话发生的更改(请参阅SET TRANSACTION)
编辑:我看到你正在使用DataSource类.我不熟悉这个类 - 我认为它是一个连接共享资源.我意识到您当前的应用程序设计可能无法在整个工作流程中轻松使用相同的连接对象(这些步骤可能设计为独立运行,并且您没有构建设施以将连接对象从一个步骤传递到但是你应该验证返回到DataSource对象的连接对象是否"干净",特别是关于打开的事务.您可能没有在代码中调用SET TRANSACTION,但是其他地方的DataSource的另一个消费者可能正在这样做,并且将连接返回到数据源,并且会话仍处于SERIALIZABLE或READ ONLY模式.连接共享时,必须先将所有连接回滚,然后再将其传递给新的用户.
如果您无法控制或查看DataSource类的行为,您可能希望尝试对新获取的连接执行ROLLBACK,以确保它没有已建立的延迟事务.
如果 DBA 团队尝试修改该max_commit_propagation_delay参数,则可能意味着您正在连接到一个 RAC 实例(即:多个不同的服务器访问一个数据库)。
在这种情况下,当您在 Java 代码中关闭并重新打开连接时,您可能会被另一台服务器回答。延迟参数意味着当两个实例不会在完全相同的时间点时,有一个小的时间范围。您得到的答案与某个时间点一致,但可能不是最新的。
正如 KM 提出的,最简单的解决方案是在提交后保持连接打开。
或者,如果可行,您也可以在关闭连接后添加延迟(例如,如果这是一个批处理作业并且响应时间并不重要)。