Oracle Partitioning Оперативне переміщення і відновлення історичних даних, oracle табличний простір, історичні дані, тимчасова таблиця, файл бази даних
- 1. Введення При вирішенні завдання зберігання і забезпечення доступу до історичних даних дуже часто...
- 3. Переміщення історичних даних
- 4. Створення тимчасової таблиці
- 5. Переміщення даних в тимчасову таблицю
- 6. Видалення зв'язків
- 7. Атрибут "тільки для читання"
- 8. Експорт табличного простору
- 9. Копіювання файлів
- 10. Створення архіву
- 11. Видалення табличного простору
- 12. Відновлення історичних даних
- 13. Копіювання і розпакування архіву
- 14. Копіювання файлів
- 15. Імпорт історичних даних
- 16. Зміна табличних просторів
- 17. Висновок
1. Введення
При вирішенні завдання зберігання і забезпечення доступу до історичних даних дуже часто виникає завдання вивантаження архівних даних на резервний носій (наприклад, на магнітну стрічку) з можливістю оперативного відновлення цієї інформації і забезпечення доступу до неї користувачів. Ця проблема найбільш актуальна для сховищ даних, хоча може застосовуватися і для обробки архівних даних OLTP-систем.
У даній статті описується спосіб вирішення цієї проблеми за допомогою опції Partitioning бази даних Oracle Database.
Нижче представлена ілюстрація даного підходу, який включає в себе: ідентифікацію історичних даних, їх переміщення в тимчасову таблицю, експорт та копіювання на резервний носій.
Ілюстрація підходу переміщення історичних даних
Першим кроком є визначення секцій, що містять історичні дані. Історичні дані - це дані за минулі періоди, над якими в майбутньому не будуть проводитися операції зміни. Потім секції, що містять історичні дані, переміщаються в заздалегідь підготовлену тимчасову таблицю. Наступним кроком проводиться експорт метаданих для Transport Table Space (TTS). У висновку проводиться перенесення файлу з метаданими і файлу табличного простору на резервний носій.
Далі буде детально розглядатися процес експорту і імпорту табличного простору для одного розділу секціонірованной таблиці CALLS (інформація про телефонні дзвінки клієнтів) схеми DWH.
SQL> CREATE TABLE DWH.CALLS (2 CALLS_ID NUMBER (15) NOT NULL, 3 STRT_DT_KEY DATE NOT NULL, 4 BSN_EV_TP_ID NUMBER (5) NOT NULL, 5 STRT_TM DATE NOT NULL, 6 END_TM DATE NOT NULL, 7 CTY_FR NUMBER (15) NOT NULL, 8 CTY_TO NUMBER (15) NOT NULL, 9 A_NUM VARCHAR2 (20) NOT NULL, 10 B_NUM VARCHAR2 (20) NOT NULL, 11 PRICE_AMT NUMBER (15,4) NOT NULL, 12 CHG_AMT NUMBER (15,4) NOT NULL, 13 CHG_CALL_DUR NUMBER (15) NOT NULL, 14 CALL_DUR NUMBER (15) NOT NULL, 15 IS_DEL_IND NUMBER (1) NOT NULL, 16 UPD_DT DATE NOT NULL, 17 PPN_DT DATE NOT NULL, 18 SRC_STM_ID NUMBER (5) NOT NULL 19 ) 20 TABLESPACE TBS_CALLS 21 PARTITION BY RANGE (STRT_DT_KEY) 22 SUBPARTITION BY LIST (BSN_EV_TP_ID) 23 SUBPARTITION TEMPLATE (24 SUBPARTITION "SP_BSNEV1" values (1), 25 SUBPARTITION "SP_BSNEV2" values (2), 26 SUBPARTITION "SP_BSNEV3" values (3 ), 27 SUBPARTITION "SP_BSNEV4" values (4), 28 SUBPARTITION "SP_BSNEV5" values (5), 29 SUBPARTITION "SP_BSNEV6" values (6), 30 SUBPARTITION "SP_BSNEV7" values (7), 31 SUBPA RTITION "SP_BSNEV8" values (8), 32 SUBPARTITION "SP_BSNEV9" values (9)) 33 (34 PARTITION P_0106 VALUES LESS THAN (TO_DATE ( '2006-02-01 00:00:00', 'SYYYY-MM-DD HH24 : MI: SS ',' NLS_CALENDAR = GREGORIAN ')) TABLESPACE TBS_CALLS_0106_1, 35 PARTITION P_0206 VALUES LESS THAN (TO_DATE (' 2006-03-01 00:00:00 ',' SYYYY-MM-DD HH24: MI: SS ' , 'NLS_CALENDAR = GREGORIAN')) TABLESPACE TBS_CALLS_0206_1, 36 PARTITION P_0306 VALUES LESS THAN (TO_DATE ( '2006-04-01 00:00:00', 'SYYYY-MM-DD HH24: MI: SS', 'NLS_CALENDAR = GREGORIAN ')) TABLESPACE TBS_CALLS_0306_1, 37 PARTITION P_MAXV VALUES LESS THAN (MAXVALUE) TABLESPACE TBS_CALLS_PMAXV 38); Table created
Описаний підхід був прийнятий як основний для задач переміщення і відновлення історичних даних сховища корпоративної інформації компанії "ВАТ Ростелеком".
2. Визначення історичних даних
Для виявлення історичних даних, тобто тих даних які не будуть більше змінюватися, адміністратор повинен щомісяця проводити моніторинг їх появи. Перелік даних, які слід визнавати історичними, визначають бізнес-вимоги. Часто правило визначення історичних даних зводиться до такої умови: історичними визнаються ті дані, термін зберігання яких перевищує певний ліміт, наприклад, 5 років від поточного моменту.
Для автоматизації виявлення історичних даних в конкретній таблиці фактів, можливо виконання наступного запиту (звернення до словника Oracle Database):
select COUNT_DAY, TABLE_OWNER, TABLE_NAME, PARTITION_NAME from (select TO_NUMBER (TO_DATE (TO_CHAR (SYSDATE, 'MM.YYYY'), 'MM.YYYY') - TO_DATE (substr (t.partition_name, 3, 2) || '.20 '|| substr (t.partition_name, 5,2),' MM.YYYY ')) AS COUNT_DAY, T.TABLE_OWNER, T.TABLE_NAME, T.PARTITION_NAME from all_tab_partitions t) where COUNT_DAY> 1825 / * 5 років в днях * /;
Даний запит поверне перелік розділів (див. Поле PARTITION_NAME) за таблицями, дані в яких є історичними (термін зберігання перевищує 5 років). Ці дані необхідно архівувати і перенести на резервний носій.
3. Переміщення історичних даних
Для переміщення розділу таблиці з історичними даними буде використана технологія переміщуються табличних просторів (Transportable Tablespace). Для переміщення табличних просторів необхідно провести наступні дії:
- Створити тимчасову таблицю, в яку будуть переміщені історичні дані.
- Перемістити в тимчасову таблицю історичні дані шляхом зміни розділів (exchange partition).
- Прибрати все логічні і фізичні зв'язку табличного простору і розділу таблиці з усіма об'єктами крім тимчасової таблиці.
- Зробити табличний простір доступним тільки для читання (read only).
- Зробити експорт метаданих табличного простору розділу з історичними даними (для успішного виконання експорту та імпорту необхідно, щоб користувач, з-під якого виконуються дані операції, мав правами exp_full_database і imp_full_database відповідно).
- Скопіювати файл з метаданими і файли даних табличного простору з історичними даними в папку для перенесення на резервний носій.
- Зробити архів, включивши в нього: файл з метаданими, файли табличного простору, додатковий файл з описом.
- Видалити табличний простір з історичними даними з БД.
Нижче наведена послідовність дій по переміщенню історичних даних з розділу P_0106 таблиці CALLS.
Дані розділу P_0106 зберігаються в табличному просторі TBS_CALLS_0106_1, яке в свою чергу, складається з двох файлів: TBS_CALLS_0106_1_001.dbf і TBS_CALLS_0106_1_002.dbf.
Нижче всі скрипти будуть виконуватися з-під користувача system.
4. Створення тимчасової таблиці
Створимо тимчасову таблицю, в яку надалі перемістимо розділ з історичними даними.
SQL> create table DWH.CALLS $ EXP $ P_0106 2 TABLESPACE TBS_CALLS_0106_HIST 3 PARTITION BY LIST ( "BSN_EV_TP_ID") 4 (5 PARTITION "SP_BSNEV1" values (1) TABLESPACE TBS_CALLS_0106_HIST, 6 PARTITION "SP_BSNEV2" values (2) TABLESPACE TBS_CALLS_0106_HIST, 7 PARTITION "SP_BSNEV3" values (3) TABLESPACE TBS_CALLS_0106_HIST, 8 PARTITION "SP_BSNEV4" values (4) TABLESPACE TBS_CALLS_0106_HIST, 9 PARTITION "SP_BSNEV5" values (5) TABLESPACE TBS_CALLS_0106_HIST, 10 PARTITION "SP_BSNEV6" values (6) TABLESPACE TBS_CALLS_0106_HIST, 11 PARTITION " SP_BSNEV7 "values (7) TABLESPACE TBS_CALLS_0106_HIST, 12 PARTITION" SP_BSNEV8 "values (8) TABLESPACE TBS_CALLS_0106_HIST, 13 PARTITION" SP_BSNEV9 "values (9) TABLESPACE TBS_CALLS_0106_HIST 14) 15 as select * from DWH.CALLS where 1 = 2; Table created
5. Переміщення даних в тимчасову таблицю
Виконуємо команду зміни розділу (exchange paertition) P_0106 (розділ з історичними даними) між таблицею CALLS і тимчасової таблицею CALLS $ EXP $ P_0106.
SQL> alter table DWH.CALLS exchange partition P_0106 with table DWH.CALLS $ EXP $ P_0106 without validation; Table altered
6. Видалення зв'язків
Зробити експорт метаданих табличного простору можна тільки тоді, коли воно не пов'язане з іншими об'єктами бази даних.
Для перевірки наявності зв'язків необхідно виконати наступні процедуру і запит (їх необхідно виконувати з-під користувача SYS):
SQL> conn sys / pass @ DWH as sysdba Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 Connected as SYS SQL> SQL> EXECUTE DBMS_TTS.transport_set_check ( 'TBS_CALLS_0106_1', TRUE); PL / SQL procedure successfully completed SQL> SELECT * FROM TRANSPORT_SET_VIOLATIONS; VIOLATIONS ------------------------------------------------- ------------------------------- Default Partition (Table) Tablespace TBS_CALLS for CALLS not contained in transp Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS $ EXP $ P_0106 no Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not Default Composite Partition (Table) Tablespace TBS_CALLS_0106_HIST for CALLS not 19 rows selected SQL>
Якщо запит до подання TRANSPORT_SET_VIOLATIONS повертає записи, то це означає, що взаємозв'язку розділу з іншими об'єктами бази даних існують. Необхідно, щоб запит до даного подання НЕ повертав рядків. Для цього необхідно змінити табличні простору для розділу P_0106 таблиці CALLS - перемістити розділ в табличний простір TBS_CALLS_0106_HIST і перемістити метадані про таблиці CALLS $ EXP $ P_0106 в табличний простір TBS_CALLS_0106_1:
SQL> ALTER TABLE DWH.CALLS MODIFY default attributes FOR PARTITION P_0106 tablespace TBS_CALLS_0106_HIST; Table altered SQL> ALTER TABLE DWH.CALLS $ EXP $ P_0106 MODIFY default attributes tablespace TBS_CALLS_0106_1; Table altered SQL>
Виконаємо перевірку наявності взаємозв'язків повторно.
SQL> EXECUTE DBMS_TTS.transport_set_check ( 'TBS_CALLS_0106_1', TRUE); PL / SQL procedure successfully completed SQL> SELECT * FROM TRANSPORT_SET_VIOLATIONS; VIOLATIONS ------------------------------------------------- ------------------------------- SQL>
У поданні TRANSPORT_SET_VIOLATIONS записи відсутні - взаємозв'язків немає.
7. Атрибут "тільки для читання"
Зробити експорт метаданих табличного простору можна тільки тоді, коли воно знаходиться в режимі "тільки для читання". Зробити табличний простір доступним тільки для читання можна, виконавши наступну команду:
SQL> ALTER TABLESPACE TBS_CALLS_0106_1 READ ONLY; Tablespace altered SQL>
8. Експорт табличного простору
Зробимо експорт метаданих табличного простору. Для цього буде використана технологія DataPump і, відповідно, утиліта expdp.
У командному рядку необхідні виконати команду експорту (див. Скрипт - export.sh ) В директорію определенною в змінної DATA_PUMP_DIR бази даних.
$ Expdp system / pass @ DWH DIRECTORY = DATA_PUMP_DIR DUMPFILE = TBS_CALLS_0106_1.DMP TRANSPORT_TABLESPACES = TBS_CALLS_0106_1 TRANSPORT_FULL_CHECK = Y LOGFILE = TBS_CALLS_0106_1.log; Export: Release 10.2.0.4.0 - 64bit Production on Friday, 17 April 2009 10:39:42 Copyright (c) 2003, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 With the Partitioning, Oracle Label Security, OLAP and Data Mining options Starting "SYSTEM". "SYS_EXPORT_TRANSPORTABLE_02": system / ******** @ DWH DIRECTORY = DATA_PUMP_DIR DUMPFILE = TBS_CALLS_0106_1.DMP TRANSPORT_TABLESPACES = TBS_CALLS_0106_1 TRANSPORT_FULL_CHECK = Y LOGFILE = TBS_CALLS_0106_1.log Processing object type TRANSPORTABLE_EXPORT / PLUGTS_BLK Processing object type TRANSPORTABLE_EXPORT / TABLE Processing object type TRANSPORTABLE_EXPORT / TABLE_STATISTICS Processing object type TRANSPORTABLE_EXPORT / POST_INSTANCE / PLUGTS_BLK Master table "SYSTEM". " SYS_EXPORT_TRANSPORTABLE_02 "successfully loaded / unloaded ******************************************** ****************************** Dump file set for SYSTEM.SYS_EXPORT_TRANSPORTABLE_02 is: /u01/app/oracle/product/10.2. 0 / db_1 / admin / DWH / dpdump / TBS_CALLS_0106_1.DMP Job "SYSTEM". "SYS_EXPORT_TRANSPORTABLE_02" successfully completed at 10:40:11 $
Перейдемо в директорію, яку визначає змінна DATA_PUMP_DIR.
$ Cd /u01/app/oracle/product/10.2.0/db_1/admin/DWH/dpdump/ $
Переглянемо її вміст.
$ Ls TBS_CALLS_0106_1.DMP TBS_CALLS_0106_1.log $
9. Копіювання файлів
Скопіюємо файл з метаданими TBS_CALLS_0106_1.DMP і файли даних БД TBS_CALLS_0106_1_001.dbf, TBS_CALLS_0106_1_002.dbf в директорію / backup / DWH / TBS_CALLS_0106_1_HIST, призначену для тимчасового зберігання архівів, перед перенесенням на резервний носій. Попередньо директорію TBS_CALLS_0106_1_HIST необхідно створити в / backup / DWH /.
$ Cd / backup / DWH / $ mkdir TBS_CALLS_0106_1_HIST $ ls TBS_CALLS_0106_1_HIST $ $ cp /u01/app/oracle/product/10.2.0/db_1/admin/DWH/dpdump/TBS_CALLS_0106_1.DMP /backup/DWH/TBS_CALLS_0106_1_HIST/TBS_CALLS_0106_1.DMP $ cp /wh/oracle/disk1/DWH/TBS_CALLS_0106_1_001.dbf /backup/DWH/TBS_CALLS_0106_1_HIST/TBS_CALLS_0106_1_001.dbf $ cp /wh/oracle/disk0/DWH/TBS_CALLS_0106_1_002.dbf /backup/DWH/TBS_CALLS_0106_1_HIST/TBS_CALLS_0106_1_002.dbf $ $ cd TBS_CALLS_0106_1_HIST / $ ls TBS_CALLS_0106_1.DMP TBS_CALLS_0106_1_001.dbf TBS_CALLS_0106_1_002.dbf $
Рекомендується створити текстовий файл /backup/DWH/TBS_CALLS_0106_1.txt, в якому описати місце розташування файлів з даними експортованого табличного простору. І потім включити даний текстовий файл в архів.
Для створення файлу з описом можна виконати наступні дії (в операційній системі Unix):
- Створити файл: touch TBS_CALLS_0106_1.txt.
- Відкрити файл на редагування: cat> TBS_CALLS_0306_1.txt.
- Внести в файл текст.
- По закінченню редагування файлу натиснути Cntr + D.
$ Touch TBS_CALLS_0106_1.txt $ cat> TTBS_CALLS_0106_1.txt /wh/oracle/disk1/DWH/TBS_CALLS_0106_1_001.dbf /wh/oracle/disk0/DWH/TBS_CALLS_0106_1_002.dbf $
10. Створення архіву
Створимо архів з вмістом директорії TBS_CDR_0306_1_HIST, використовуючи утиліту tar. Цей архів, згодом, і буде переміщений на резервний носій.
$ Cd backup / DWH / $ tar -cf - TBS_CALLS_0106_1_HIST | gzip -c> TBS_CALLS_0106_1_HIST.tar.gz $ ls TBS_CALLS_0106_1_HIST TBS_CALLS_0106_1_HIST.tar.gz $
Архів створено. Тепер можна видалити історичні дані з таблиці БД.
11. Видалення табличного простору
Видалимо табличний простір TBS_CALLS_0106_1
SQL> drop tablespace TBS_CALLS_0106_1 including contents and datafiles; Tablespace dropped SQL>
Разом з табличним TBS_CALLS_0106_1 простором віддалиться і тимчасова таблиця CALLS $ EXP $ P_0106.
Для полегшення надалі процесу відновлення в таблиці з даними (в нашому прикладі це таблиця CALLS) розділ, в якому були історичні дані, краще залишити.
12. Відновлення історичних даних
Для відновлення історичних даних з архіву необхідно провести наступні дії:
- Скопіювати архів з історичними даними з резервного носія в директорію для відновлення.
- Розпакувати архів.
- Скопіювати файл з метаданими в папку для відновлення і файлів з даними в папку (або папку) сервера бази даних, де вони перебували до проведення експорту.
- Імпорт історичних даних в тимчасову таблицю.
- Зміна табличних просторів.
13. Копіювання і розпакування архіву
Скопіюємо архів з історичними даними з резервного носія в директорію для відновлення. У нашому прикладі це буде директорія / backup / Restore. Зазвичай цю функцію виконує адміністратор системи резервного копіювання.
Підключимося до сервера, на якому працює наша СУБД, під користувачем операційної системи oracle, використовуючи командний рядок.
login as: oracle Using keyboard-interactive authentication. Password:
Ізвлечём файли з архіву.
$ Cd / backup / Restore / $ gunzip -c TBS_CALLS_0106_1_HIST.tar.gz | tar -xf - $
14. Копіювання файлів
Скопіюйте файл з метаданими TBS_CALLS_0106_1.DMP в директорію /u01/app/oracle/product/10.2.0/db_1/admin/DWH/dpdump/,
файл даних TBS_CALLS_0106_1_001.dbf в директорію / wh / oracle / disk1 / DWH /;
файл даних TBS_CALLS_0106_1_002.dbf в директорію / wh / oracle / disk0 / DWH /.
$ Cp /bkup/Restore/TBS_CALLS_0106_1_HIST/TBS_CALLS_0106_1.DMP /u01/app/oracle/product/10.2.0/db_1/admin/DWH/dpdump/TBS_CALLS_0106_1.DMP $ $ cp /bkup/Restore/TBS_CALLS_0106_1_HIST/TBS_CALLS_0106_1_001.dbf / wh / oracle / disk1 / DWH / TBS_CALLS_0106_1_001.dbf $ $ cp /bkup/Restore/TBS_CALLS_0106_1_HIST/TBS_CALLS_0106_1_002.dbf /wh/oracle/disk0/DWH/TBS_CALLS_0106_1_002.dbf $
15. Імпорт історичних даних
Виконаємо команду експорту метаданих табличного простору (див. Скрипт - import.sh ) В директорію, певну в змінної DATA_PUMP_DIR бази даних.
$ Impdp system / pass @ DWH DIRECTORY = DATA_PUMP_DIR DUMPFILE = TBS_CALLS_0106_1.DMP TRANSPORT_DATAFILES = / wh / oracle / disk1 / DWH / TBS_CALLS_0106_1_001.dbf, /wh/oracle/disk0/DWH/TBS_CALLS_0106_1_002.dbf; Import: Release 10.2.0.4.0 - 64bit Production on Friday, 17 April 2009 11:08:44 Copyright (c) 2003, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 With the Partitioning, Oracle Label Security, OLAP and Data Mining options Master table "SYSTEM". "SYS_IMPORT_TRANSPORTABLE_01" successfully loaded / unloaded Starting "SYSTEM". "SYS_IMPORT_TRANSPORTABLE_01": system / ******** @ DWH DIRECTORY = DATA_PUMP_DIR DUMPFILE = TBS_CALLS_0106_1.DMP TRANSPORT_DATAFILES = / wh / oracle / disk1 / DWH / TBS_CALLS_0106_1_001.dbf, /wh/oracle/disk0/DWH/TBS_CALLS_0106_1_002.dbf Processing object type TRANSPORTABLE_EXPORT / PLUGTS_BLK Processing object type TRANSPORTABLE_EXPORT / TABLE Processing object type TRANSPORTABLE_EXPORT / TABLE_STATISTICS Processing object type TRANSPORTABLE_EXPORT / POST_INSTANCE / PLUGTS_BLK Job "SYSTEM". "SYS_IMPORT_TRANSPORTABLE_01" successfully completed at 11:08:51 $
Після закінчення імпорту метаданих табличного простору в схемі DWH з'явиться таблиця CALLS $ EXP $ P_0106.
16. Зміна табличних просторів
Здійснимо зміну (partitio6 exchange) між таблицею CALLS $ EXP $ P_0106 і таблиці CALLS.
SQL> alter table DWH.CALLS exchange partition P_0106 with table DWH.CALLS $ EXP $ P_0106 without validation; Table altered SQL> У разі, якщо це необхідно, можна змінити атрибут «тільки для читання». SQL> ALTER TABLESPACE TBS_CALLS_0106_1 READ WRITE; Tablespace altered SQL>
17. Висновок
База даних Oracle Database надає гнучкий механізм управління табличними просторами секціонованих таблиць, що дозволяє досить просто організувати управління архівними даними, як в OLTP-системах, так і в сховищах даних.
Повний архів скриптів можна завантажити за цим посиланням.
18. Додаткова інформація
- Oracle Database Utilities 10g Release 2 (10.2) Part Number B14215-01 (розділ присвячений DataPump).
- Doc ID: 09585.1 від 04.09.2002 на Oracle Metalink.
- Doc ID: 114915.1 від 30.03.2008 на Oracle Metalink.