簡體   English   中英

原子地更新多行

[英]Update more than one row atomically

我需要執行一個select,然后以原子方式更新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)

但是,這不會解決您的第二個問題,即嘗試更新同一個表的兩種競爭方法 - 競爭條件。 在我看來,這里有兩種主要方法 - 每種方法都有它的優點和缺點。

最簡單的方法是鎖定表 - 這需要最少的代碼更改,但有一個很大的缺點。 假設,與大多數應用程序一樣,更多的是讀取寫入:鎖定表將阻止所有其他用戶查看數據,代碼可能會掛起,等待鎖定在連接超時之前釋放踢出並拋出異常。

更復雜的方法是確保以線程安全的方式實現執行這些更新的方法。 為此:

  • 該表的所有更新都通過一個類
  • 該類實現Singleton模式,或將更新方法公開為Static方法
  • 更新方法使用Synchronized關鍵字來防止競爭條件

使用交易。

如果任何其他進程通過updateRow()更改了您正在更新的數據庫行,會發生什么? 有沒有辦法鎖定ResultSet中的行?

在Oracle中,您可以通過發出以下SQL來標記某些行以進行更新。

select cola, colB from tabA for update;

嘗試更新此行的下一個事務/線程/應用程序將獲得異常。 有關詳細信息,請參閱此處 - http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4530093713805

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM