oracle 10g - отслеживает удаление больших строк - PullRequest
0 голосов
/ 19 марта 2009

как я могу отслеживать удаление строк (скажем, 20 строк)? Подумайте, я dba и слежу за базой данных оракула. ​​Мне нужно получить предупреждение, если кто-то удаляет более 20 строк.

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

Ответы [ 5 ]

3 голосов
/ 19 марта 2009

Что вы надеялись сделать, если такое удаление произойдет? Если вы не сохранили удаленные строки где-то (что потребовало бы триггера), вы не сможете их вернуть, и даже не можете знать, что они были.

Если удаление строк является проблемой и восстановление, вероятно, потребуется, не допускайте удаления строк: добавьте «удаленный» столбец и задайте его значение в ОБНОВЛЕНИИ, а не УДАЛИТЬ (или добавьте триггер)

В качестве альтернативы, возможно, вы могли бы найти способ разобрать журналы повторов? Я никогда не пробовал, но думаю, что это возможно, если приложить достаточные усилия.

Лично я думаю, что я бы:

  1. пересмотреть «необходимость» знать об удалениях, и если я не могу это изменить,
  2. преодолеть мой страх перед триггерами.
1 голос
/ 19 марта 2009

Итак, для обзора: вы запрашиваете способ мониторинга, но без использования триггера, потому что выполнение этого кода «дорого» для каждого оператора DELETE.

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

0 голосов
/ 21 марта 2009

"Как я могу проанализировать журнал повторов и перехватить sql, который мог вызвать массовое удаление строк? Мой сценарий таков, как только происходит массовое удаление строк" О каком удалении вы говорите?

УДАЛЕНИЕ ИЗ таблицы, ГДЕ pk IN (1, .... 50) может удалить пятьдесят строк за одно выполнение оператора

FORALL i IN 1..50
 DELETE FROM table WHERE pk = i;

будет иметь пятьдесят выполнений, каждое из которых удалит одну строку в одной транзакции.

FOR i IN 1..50 LOOP
 DELETE FROM table WHERE pk = i;
 COMMIT;
END LOOP;

будет иметь пятьдесят выполнений, каждое из которых удалит одну строку из пятидесяти транзакций за один сеанс.

Так вы ищете удаления более 20 строк в одном операторе, транзакции или сеансе? Принимая самый простой вариант. Логически, после каждого оператора DELETE вам нужно будет посмотреть количество обработанных строк и, если их больше 20, создать запись аудита. Технически, способ выполнить такой тест - создать триггер уровня строки AFTER DELETE на таблице. Любая альтернатива будет иметь точно такое же влияние на производительность, как и та же самая работа. Пределы уровня транзакции или сеанса были бы аналогичными, но вам потребуется триггер, чтобы вести подсчет количества удаленных записей (например, в переменной уровня пакета).

0 голосов
/ 20 марта 2009

Если вы не хотите использовать триггер, вы должны установить и настроить аудит базы данных в качестве dba. С помощью функции аудита вы можете отслеживать, кто что сделал и когда, а кто должен быть уведомлен. Вы также можете вернуть удаленные строки с помощью функции возврата назад, если период удаления не превысил срок хранения отмены. После этого вы можете использовать logminer для возврата удаленных строк из архивных / повторных журналов, анализируя журналы за этот период времени.

0 голосов
/ 20 марта 2009

Используйте процедуру для процесса удаления и добавьте SQL% ROWCOUNT, чтобы отслеживать, сколько строк было удалено. Вот пример из документации Oracle по использованию SQL% ROWCOUNT:

CREATE TABLE employees_temp AS SELECT * FROM employees;

DECLARE
  mgr_no NUMBER(6) := 122;
BEGIN
  DELETE FROM employees_temp WHERE manager_id = mgr_no;
  DBMS_OUTPUT.PUT_LINE('Number of employees deleted: ' || TO_CHAR(SQL%ROWCOUNT));
END;
/

Если вы хотите использовать оператор FORALL, вы можете использовать SQL% BULK_ROWCOUNT так же, как SQL% ROWCOUNT, вот еще один пример из документации Oracle:

CREATE TABLE emp_temp AS SELECT * FROM employees;

DECLARE
   TYPE NumList IS TABLE OF NUMBER;
   depts NumList := NumList(30, 50, 60);
BEGIN

   FORALL j IN depts.FIRST..depts.LAST
      DELETE FROM emp_temp WHERE department_id = depts(j);

   -- How many rows were affected by each DELETE statement?
   FOR i IN depts.FIRST..depts.LAST
   LOOP
      DBMS_OUTPUT.PUT_LINE('Iteration #' || i || ' deleted ' || SQL%BULK_ROWCOUNT(i) || ' rows.');
   END LOOP;

END;
/

Если у вас действительно есть или вы хотите избежать триггеров, я думаю, вы должны пойти по этому пути.

...