题
我需要执行一个选择,然后更新一些行 ResultSet
在原子的方式。
代码,我在使用的看起来像(简化):
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("SELECT ...");
while (rs.next()) {
if (conditions_to_update) {
rs.updateString(...);
rs.updateRow();
}
}
- 我可以保证更新是要执行原子?如果不是,我怎么保证?
- 会发生什么情况如果任何其他进程已经改变了数据库的行正在更新过
updateRow()
?是否有任何方式对锁定行的ResultSet
?
解决方案
有可能是一堆的技术和概念来到这里,事情开始变得相当的粘性的时候你开始考虑多螺纹/多的要求的应用。
作为Iassevk说,你应该看看使用 交易 为确保原子的性质的更新--一个非常低的水平的例子就是做沿线的东西:
...
con.setAutoCommit(false);
try {
while (rs.next()) {
if (conditions_to_update) {
rs.updateString(...);
rs.updateRow();
}
}
con.setAutoCommit(true);
} catch (Exception ex) {
//log the exception and rollback
con.rollback();
} finally {
con.close();
}
所有更新,然后将批成相同交易。如果任何更新所产生的一个例外(例如一个值无效或连接失败的部分方式通过的结果),整个大会被卷回来。(最后加入的,因为我是一个冠军;p)
然而,这不会解决你的第二个问题是两个相互竞争的方法试图更新相同的表一种竞争条件。有,在我的脑海里,两个主要的方法在这里-每个人都有它的优点和缺点。
最简单的方法就是 锁定本台 -这将要求最小的代码变化,但有一个相当大的缺点。工作上的假设是,与大多数应用中,更多的读写:锁定本台将防止所有其它用户查看数据,与可能性的代码就挂,等待锁定释放之前的连接时在踢,并引发一个例外。
更复杂的方法是确保该方法用于执行这些更新实行的在线安全的方式。为此目的:
- 所有的更新,为此表过一个类
- 这类实现一个单一的模式,或是公开的更新方法以静态的方法
- 更新方法的使用 同步 关键词以防止比赛的条件
其他提示
使用的交易。
会发生什么情况如果任何其他进程已经改变的数据库行,更新经由updateRow()?是否有任何方式对锁定的行结果?
在Oracle,你可以有点标定的行更新,发出了下列SQL。
select cola, colB from tabA for update;
下交易/螺纹/应用程序,试图更新这种行将得到一个例外。看到这更多的细节-- http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4530093713805
不隶属于 StackOverflow