Дек 122014
 

Режим FORCE LOGGING нужно обязательно устанавливать на каждой вновь созданной базе, чтобы исключить проведение нелогируемых операций. Это абсолютно необходимо для нормальной работы DataGuard, репликации и успешного восстановления из резервных копий. Но бывают базы (обычно это хранилища данных), на которых ведётся обработка больших объёмов данных, потеря которых некритична (эти данные берутся, например, из других источников, и в случае потери их можно восстановить за приемлемое время, не прибегая к полному восстановлению из бэкапа). В таком случае было бы удобно отключить режим FORCE LOGGING на некоторых табличных пространствах, чтобы получить выигрыш в скорости обработки и уменьшить объём генерации redo-логов.
Проблема в том, что когда FORCE LOGGING включён на уровне всей БД, параметры логирования для отдельных табличных пространств игнорируются. Если же FORCE LOGGING на уровне базы отключить, чтобы создать табличное пространство для временных данных (не путать с temporary tablespace), то весьма велик риск при создании нового табличного пространства забыть явно включить для него FORCE LOGGING, и заметить это слишком поздно.
Решение - небольшой триггер, который не даст совершить подобную ошибку. Рассмотрим пример отключения FORCE LOGGING на одном из табличных пространств:

-- Отключим FORCE LOGGING на всей базе
ALTER DATABASE NO FORCE LOGGING;
 
-- Теперь включим FORCE LOGGING на всех ТП, 
-- содержащих критичные данные
ALTER TABLESPACE SYSTEM FORCE LOGGING;
ALTER TABLESPACE sysaux FORCE LOGGING;
ALTER TABLESPACE users FORCE LOGGING;
-- ....
 
-- Теперь отключим этот режим на ТП hugets
ALTER TABLESPACE hugets NO FORCE LOGGING;

Теперь создадим триггер, который будет выдавать ошибку при попытке создать табличное пространство без явного указания режима FORCE LOGGING:

CREATE OR REPLACE TRIGGER force_logging_trig
BEFORE CREATE ON DATABASE
DECLARE
	sql_text	DBMS_STANDARD.ora_name_list_t;
	v_stmt		VARCHAR2(2000);
	n		PLS_INTEGER;
BEGIN
 
IF (ora_dict_obj_type = 'TABLESPACE' ) AND (ora_sysevent = 'CREATE') THEN 
	n := ora_sql_txt(sql_text);
	FOR i IN 1..n LOOP
		v_stmt := v_stmt || sql_text(i);
	END LOOP;
 
	IF (UPPER(v_stmt) NOT LIKE '%FORCE%LOGGING%') THEN 
		raise_application_error(-20001, 'Disable force_logging_trig trigger to create the nologging TS!');
	END IF;
 
END IF;
 
END force_logging_trig;
/

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

(обязательно)

(обязательно)