Для этих целей в ORACLE можно использовать замечательный инструмент- FLASHBACK.
FB позиционируется ORACLом как инструмент dba обеспечивающий ретроспективные запросы к таблицам
для восстановления утерянной по каким-либо причинам информации либо отката всех изменений к моменту времени в прошлом.
Один из режимов чтения работает по опции SCN(System Change Number).
Зафиксировав значение SCN можно читать произвольный обьем логически согласованой информации примерно DB_FLASHBACK_RETENTION_TARGET минут.
Пост не претендует на исчерпывающее описание функционала FB поэтому приведенный ниже пример cхематичен и достаточен для демонстрации его нетрадиционного применения.
Проверяем доступность опции FLASHBACK.
SELECT FLASHBACK_ON FROM V$DATABASE;
Выдаем учетке под которой работает выгрузка необходимые права.
grant execute on SYS.DBMS_FLASHBACK to LOADER;
Значение SCN можно получить несколькими способами.
select sys.DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER from dual;
select TIME_DP, SCN from sys.smon_scn_time order by scn desc;
SELECT TIMESTAMP_TO_SCN(sysdate-1/(24*60)) from dual;
Проверяем велосипед на ходу.
create table FB_TABLE( p1 VARCHAR2(64));
select sys.DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER from dual;
GET_SYSTEM_CHANGE_NUMBER
8842201836421
insert into FB_TABLE (p1) values ('string_1');
commit;
select sys.DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER from dual;
GET_SYSTEM_CHANGE_NUMBER
8842201836472
update FB_TABLE set p1='string_2';
commit;
select sys.DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER from dual;
GET_SYSTEM_CHANGE_NUMBER
8842201836530
select t.* from FB_TABLE AS OF SCN 8842201836421 t;
P1
select t.* from FB_TABLE AS OF SCN 8842201836472 t;
P1
string_1
select t.* from FB_TABLE AS OF SCN 8842201836530 t;
P1
string_2
По данной технологии несколько лет online собирается информация c нескольких десятков OLTP-серверов на сервер аналитики.
Комментарии (9)
ComodoHacker
01.06.2016 13:46+1FLASHBACK — это общее маркетинговое название, часто вызывающее путаницу (как и многие подобные у Оракла). Следует различать входящие в него технологии.
- Flashback Query — это возможность получать данные отдельных таблиц БД на определенный момент времени в прошлом (SELECT… FROM… AS OF ...)
- Flashback Database — возможность восстановить согласованное состояние всей БД на момент времени в прошлом.
Так вот, для первого не требуется включения Flashback на уровне базы (FLASHBACK_ON в V$DATABASE). И параметр DB_FLASHBACK_RETENTION_TARGET к первому не имеет отношения. Данные берутся из UNDO и их наличие там регулируется параметром UNDO_RETENTION.
Для выполнения flashback query, помимо обычного права SELECT на таблицы, пользователю нужно дать право FLASHBACK на те же таблицы, либо системное право FLASHBACK ANY TABLE.zip_zero
01.06.2016 14:01+2С вашего позволения дополню.
Чтобы обеспечить такую технологию работы, нужно убедиться, что у нас есть достаточное количество UNDO.
Рассчитывается как undo_size = undo_retention * db_block_size * undo_block_per_sec
А примерный порядок OLTP нагрузки — undo_block_per_sec — можно прикинуть так:
SELECT MAX(undoblks/((end_time-begin_time)*3600*24)) undo_block_per_sec FROM v$undostat
Cubus
03.06.2016 23:08А чем DataPump не устраивает?
Делаем просто
$ expdp DUMPFILE=file.dmp TABLES=(T1,T2) FLASHBACK_TIME=(sysdate-24)
Или с помощью impdp через dblink.
Следующая ступень Кунг-фу — использование пакета dbms_datapump для таких вещей.
Том Кайт справедливо говорил, что если в Oracle есть некий функционал, то дублировать его не стоит.
hellamps
не очень хорошая идея:
1) создается нагрузка на продакшн
2) flashback — часть функционала Enterprise Edition — другие деньги за лицензирование
3) DB_FLASHBACK_RETENTION_TARGET не дает 100% гарантии получения снэпшота за этот ретеншн.
Если стоит цель просто получить текущий консистентный набор данных, то всё гораздо проще, достаточно поставить SERIALIZABLE транзакционный уровень изоляции и просто выбрать данные.
А если стоит задача сделать постоянный процесс — почему не взять и сделать master-slave репликацию на сервер аналитики или на промежуточный сервер для ETL? Есть куча средств, начиная от ораклового GoldenGate до всяких SymmetricDS. В простейшем случае это вообще standby юнит, останавливаете применение логов = неизменяемый снепшот, выгрузили данные, поехали дальше апплаить… Этим может заниматься пассивный юнит, чтобы не простаивал, например.
ComodoHacker
hellamps
Если мы берем flashback query — то и там и там механизм один и тот же — UNDO, и там и там будет snapshot too old если данные из undo ушли. Расскажете, чем будет отличаться в этой самой OLTP нагрузке сессия которая по прочитанному SCN будет делать flashback query от serializable транзакции? Или, таки, ничем?
ComodoHacker
Она не будет мешать другим сессиям.
hellamps
Никаких блокировок сессия с serializable не создает, мы же не в MS SQL, прости господи:
SQL> select lo.session_id
2, lo.oracle_username locker
3, lo.os_user_name,o.owner||'.'||o.object_name object
4, o.object_type
5, decode(lo.locked_mode,
6 1, 'No Lock',
7 2, 'Row Share',
8 3, 'Row Exclusive',
9 4, 'Shared Table',
10 5, 'Shared Row Exclusive',
11 6, 'Exclusive') locked_mode
12 from v$locked_object lo, dba_objects o
13 where lo.object_id=o.object_id;
SESSION_ID LOCKER OS_USER_NAME OBJECT OBJECT_TYPE LOCKED_MODE
— — — — — —
SQL> alter session set isolation_level=serializable;
Session altered
SQL>
SQL> select lo.session_id
2, lo.oracle_username locker
3, lo.os_user_name,o.owner||'.'||o.object_name object
4, o.object_type
5, decode(lo.locked_mode,
6 1, 'No Lock',
7 2, 'Row Share',
8 3, 'Row Exclusive',
9 4, 'Shared Table',
10 5, 'Shared Row Exclusive',
11 6, 'Exclusive') locked_mode
12 from v$locked_object lo, dba_objects o
13 where lo.object_id=o.object_id;
SESSION_ID LOCKER OS_USER_NAME OBJECT OBJECT_TYPE LOCKED_MODE
— — — — — —
SQL>
Oracle использует оптимистический подход к блокировкам, и ничего заранее не блокирует и никого не приостанавливает. Предположим такой вариант: сессия ставит себе isolation_level=serializable, а другая сессия после этого апдейтит какую-то строчку. Затем, наша serializable сессия пробует обновить эту строчку. Где-то в другой вселенной первый апдейт должен был быть заблокирован нашей сессией, но не в оракле, в оракле мы получим во втором апдейте ORA-08177: can't serialize access for this transaction. Таким образом наша транзакция никого не будет держать(ну кроме конкуренции за shared pool, т.к. нужно snapshot востанавливать для сессии и память на это тратить…
hellamps
еще пять копеек от коллег: flashback query никогда не учавствует в shared cursors, т.е. каждый селект с флэшбеком это и parse и flood в library cache. Т.е. для продакшена это вообще, никак-никак не рекомендуется в каком-то повторяющемся коде.