2008-10-17 4 views
4

Мне нужно выполнить выбор, а затем обновить некоторые строки в 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?

ответ

4

Существует, вероятно, целая куча технологий и понятий, которые здесь вступают в силу, и все начинает становиться довольно липким, когда вы начинаете рассматривать многопоточные/многопроцессорные приложения.

Как указано Iassevk, вы должны смотреть в использовании Transactions, чтобы обеспечить атомарный характер ваших обновлений - пример очень низкого уровня будет делать что-то вдоль линий:

... 
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)

Это, однако, не будет касаться вашей второй проблемы, которая представляет собой два конкурирующих метода, пытающихся обновить ту же таблицу - состояние гонки. Здесь, на мой взгляд, есть два основных подхода: у каждого есть свои достоинства и недостатки.

Самый простой подход - Lock the table - это потребует минимальных изменений кода, но имеет довольно большой недостаток. Исходя из предположения, что, как и в большинстве приложений, более читается, что запись: блокировка таблицы будет препятствовать просмотру данных другими пользователями, причем вероятность того, что код будет висеть, ожидает блокировки до истечения времени ожидания соединения ногами и выбрасывает исключение.

Более сложный подход заключается в обеспечении того, чтобы методы для выполнения этих обновлений были реализованы поточно-безопасным способом. С этой целью:

  • Все обновления для этой таблицы проходят через один класс
  • Этот класс реализует паттерн Singleton, или предоставляет методы обновления как статические методы
  • Методы обновления используют Synchronized ключевое слово в предотвращающие условия гонки
+0

Спасибо. Я искал метод блокировки таблицы, конкретной строки или даже одной ячейки с использованием JDBC (или, по крайней мере, стандартного SQL). Полагаю, это невозможно. – 2008-10-17 18:09:38

0

Использование сделок.

0

что произойдет, если какой-либо другой процесс изменил базы данных строки, которые вы обновляете через 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

Смежные вопросы