2015-11-06 2 views
3

Я планирую сделать долгое обновление на моей огромной таблице (более миллиарда строк). Это обновление будет умножать значения одного столбца на фиксированное число.PL/SQL - не обновлять измененные строки

Проблема заключается в том, что во время моего обновления (которое может продолжаться несколько часов) обязательно будут короткие транзакции, которые будут обновлять некоторые строки, и эти строки будут иметь правильное значение, которое не должно обновляться, хотя они все равно будут удовлетворять условию моего обновления.

Итак, вопрос в том, как я могу пропустить (не обновлять) строки, которые были обновлены за пределами транзакции моего давно работающего обновления?

+0

Предположим, что короткие транзакции не придут во время длительной транзакции. Но есть несколько коротких транзакций, которые запускали и обновляли некоторые строки до начала длительной транзакции. Итак, эти строки будут правильными. Как вы знаете, чтобы пропустить их? (Я хочу сказать, что ваша проблема не имеет ничего общего с транзакцией или параллелизмом, но качество и согласованность данных) –

ответ

0

О, я совсем забыл об этом вопросе. Итак, я создал моментальный снимок текущих строк, сохранив их копии в другой таблице (мне пришлось обновлять только те строки, которые удовлетворяли заданному условию). После этого я обновил строки, которые не изменили их значения (используя слияние).

4

Один из способов - использовать ДЛЯ ОБНОВЛЕНИЯ ПРОПУСТИТЬ ЗАКАЗАТЬ, чтобы другие сеансы не смогли выбрать строки, которые уже выбраны для обновления.

Например,

Сессия 1:

SQL> SELECT empno, deptno 
    2 FROM emp WHERE 
    3 deptno = 10 
    4 FOR UPDATE NOWAIT; 

    EMPNO  DEPTNO 
---------- ---------- 
     7782   10 
     7839   10 
     7934   10 

SQL> 

Сессия 2:

SQL> SELECT empno, deptno 
    2 FROM emp WHERE 
    3 deptno in (10, 20) 
    4 FOR UPDATE NOWAIT; 
    FROM emp WHERE 
     * 
ERROR at line 2: 
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired 

Теперь давайте пропустить строки которые заблокированные сессии 1.

SQL> SELECT empno, deptno 
    2 FROM emp WHERE 
    3 deptno IN (10, 20) 
    4 FOR UPDATE SKIP LOCKED; 

    EMPNO  DEPTNO 
---------- ---------- 
     7369   20 
     7566   20 
     7788   20 
     7876   20 
     7902   20 

SQL> 

Так, отдел = 10 были заблокированы сессии 1, а затем отдел = 20 блокированы сессии 2.

+0

- это пессимистическая блокировка? – Moudiz

+1

@Moudiz Да, пессимистическая блокировка в среде состояния. –

+0

Но это не сработает, если сеанс 1 запущен после сеанса 2, правильно? –

1

я сделал что-то вроде вашей проблемы, но мой стол не слишком огромный, как ваш.

Я переработал свой стол, добавил 2 колонки.

created_date: Триггер помещает sysdate при вставке данных.

modified_date: Trigger put sysdate при обновлении данных.

Тогда я могу использовать created_date или modified_date в разделе where.

Пример:

UPDATE TABLE table_name 
SET column_name = 'values' 
WHERE created_date < SYSDATE; 

Я надеюсь, что это поможет.

+0

Это была моя первая идея, но, к сожалению, изменение структуры таблицы не является вариантом. –

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