Oracle DB, Oracle APEX, Linux etc.

вторник, 25 октября 2016 г.

Oracle Multitenant: Data Pump + DATA_PUMP_DIR = ORA-39001

Основная фича Oracle 12c -- Multitenant -- вместе с удобством администрирования привнесла и проблемы. Одна из них -- невозможность экспорта из и импорта в подключаемые БД, используя создаваемую по умолчанию директорию DATA_PUMP_DIR:

The default Data Pump directory object, DATA_PUMP_DIR, does not work with PDBs. You must define an explicit directory object within the PDB that you are exporting or importing.

При этом вы можете спокойно использовать эту директорию из подключаемой БД, работая с файлами через UTL_FILE. Похоже, проблема в том, что Data Pump фильтрует доступные в БД директории по ORIGIN_CON_ID:

SQL> select origin_con_id
  2    from dba_directories
  3   where directory_name = 'DATA_PUMP_DIR'
  4  /

ORIGIN_CON_ID
-------------
            1

SQL> show con_id

CON_ID
-------------
3 

Проблема решается одним из двух способов:
  1. Создать свою директорию в подключаемой БД и дать права на её чтение и запись отдельному пользователю, если требуется:

    SQL> create directory pdb1_data_pump_dir as '/path/to/dir';
    
    Directory created.
    
    SQL> grant read, write on directory pdb1_data_pump_dir to system;
    
    Grant succeeded.
  2. Удалить директорию DATA_PUMP_DIR в корневом контейнере и создать её там с параметром сессии "_oracle_script"=FALSE, а затем создать её же в каждой подключаемой БД (и в шаблоне БД):
    SQL> conn / as sysdba
    Connected.
    SQL> show con_id
    
    CON_ID
    ----------------
    1
    
    SQL> drop directory data_pump_dir;
    
    Directory dropped.
    
    SQL> alter session set "_oracle_script" = false;
    
    Session altered.
    
    SQL> create directory data_pump_dir as '/path/to/dir';
    
    Directory created.
    
    SQL> grant read, write on directory data_pump_dir to system;
    
    Grant succeeded.
    
    SQL> alter session set container = pdb1;
    
    Session altered.
    
    SQL> create directory data_pump_dir as '/path/to/dir';
    
    Directory created.
    
    SQL> grant read, write on directory data_pump_dir to system;
    
    Grant succeeded.

Читать далее

четверг, 21 июля 2016 г.

ORA-28374, OPEN_NO_MASTER_KEY и другие проблемы, связанные с TDE

Хорошая статья, подробно описывающая проблемы, возникающие с ключами и их хранилищами для Transparent Data Encryption, причины возникновения и решения: Oracle Public Cloud Database Service – ORA-28374: typed master key not found in wallet by Seth Miller.
Читать далее

вторник, 5 мая 2015 г.

ORDS 3.0: Проблема с настройкой подключения к нескольким БД

Один экземпляр Oracle REST Data Services (ORDS) может работать сразу с несколькими базами данных. Для этого необходимо задать настройки для подключения к ним и выбрать метод, по которому ORDS будет определять, к какой БД хочет обращается клиент. Подробней можно прочитать здесь: REST Data Services Installation, Configuration, and Development Guide — 2.1 Configuring Multiple Databases.

Но недавно вышедший ORDS 3.0.0.121 при добавлении настроек для дополнительной БД создаёт неверные файлы конфигурации. Как пример, результат настройки для базы с именем apex40:

$ java -jar ords3.war setup --database apex40
[skipped]
$ cd $APEX_CONFIG_DIR/conf
$ cat apex40.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Tue May 05 01:49:57 EEST 2015</comment>
<entry key="db.password">...</entry>
<entry key="db.username">APEX_PUBLIC_USER</entry>
</properties>
Отсутствуют имя хоста и порт (что в моём случае несущественно), имя службы. Без этой информации ORDS использует настройки подключения по умолчанию из $APEX_CONFIG_DIR/defaults.xml и подключается не к той БД.

Исправить досадный баг просто, достаточно добавить настройки подключения в файлы $APEX_CONFIG_DIR/conf/<имя_БД>*.xml вручную:




Saved on Tue May 05 01:49:57 EEST 2015
...
...
...
...
APEX_PUBLIC_USER

Надеюсь, это поправят в ближайшем обновлении ORDS.

Читать далее

понедельник, 4 мая 2015 г.

Немного камней по дороге к APEX 5.0

Как писал раньше, для начала планировал создать отдельную подключаемую БД, в которой уже потом разворачивать APEX 5.0. Для этого решил создать контейнерную БД Oracle 12.1.0.2.3 (CDB) на Linux 86-64, смигрировать уже имеющуюся холодную не-контейнерную БД (non-CDB) в виде подключаемой (PDB) в новосозданную и на её копию установить новый APEX. Создал и обновил БД, на следующем шаге воспользовался руководством: Multitenant : Migrate a Non-Container Database (CDB) to a Pluggable Database (PDB) in Oracle Database 12c Release 1 (12.1). И это было ошибкой. :)

Как промежуточный результат, получил CDB, в которой APEX уже был установлен в корневом контейнере и мог быть обновлён только для всех контейнеров сразу. Если попытаться обновить его только в одном из контейнеров, то те из них, в которых версия APEX не совпадала с версией в корневом контейнере, просто открывались в ограниченном режиме, оставляя сообщения об ошибках в PDB_PLUG_IN_VIOLATIONS:

> alter session set container=cdb$root

session SET altered.

> select message from pdb_plug_in_violations 
 where type = 'ERROR' 
   and status <> 'RESOLVED';

MESSAGE                                                                                            
----------------------------------------------------------------------------------------------------
APEX mismatch: PDB installed version 4.2.6.00.03 CDB installed version 4.2.5.00.08                   

Поэтому пришлось удалять полученную PDB, затем удалять APEX из CDB (Multitenant : Uninstall APEX from the CDB in Oracle Database 12c Release 1 (12.1)) и создавать PDB как копию non-CDB с установленным APEX заново. Но и на этом всё не закончилось: PDB открывалась со следующей ошибкой:

Sync PDB failed with ORA-65177 during 'alter user APEX_PUBLIC_USER account unlock'

Гугл на это сказал немного, как и MOS. Поскольку в корневом контейнере такого пользователя не обнаружил, а в PDB у него были лишь права DML на FLOWS_FILES.WWV_FLOW_FILE_OBJECTS$, то решил его пересоздать в PDB, не мудрствуя лукаво:

conn / as sysdba
alter session set container=pdb1;
drop user apex_public_user;

На что Oracle ответил:

28014. 00000 -  "cannot drop administrative users"
*Cause:    An attempt was made to drop administrative users.
           Administrative users can be dropped only by SYS during
           migration mode.
*Action:   Try dropping administrative users during migration mode.

Немного погуглив, изменил подход:
alter pluggable database pdb1 close immediate;
alter pluggable database pdb1 open upgrade;
alter session set "_oracle_script"=true;
alter session set container=pdb1;
drop user apex_public_user;
alter pluggable database pdb1 close;
alter pluggable database pdb1 open;
PDB открылась без ошибок. После этого можно было пересоздать пользователя APEX_PUBLIC_USER:
alter session set container=pdb1;
create user apex_public_user identified by apex_public_user;
grant select, insert, update, delete on flows_files.WWV_FLOW_FILE_OBJECTS$ 
  to apex_public_user;
grant connect to apex_public_user;

Пользователь на месте, PDB успешно открыта. Увы, попытка достучаться из ORDS к базе возвращала 503 Service unavailable. В alert.log нашёл «воодушевляющее» сообщение:

ORA-00600: internal error code, arguments: [kpdbAttachSga: bad pdb], [0], [pdb1.workgroup], [], [],[], [], [], [], [], [], []

Поиск на MOS вывел на похожий параметром ORA-00600 баг 20438519 и устраняющий его патч 19972766. После установки последнего наконец-то всё заработало.

Читать далее

понедельник, 20 апреля 2015 г.

Oracle APEX 5.0!

Вот так пару дней поболел и пропустил выход долгожданной новой версии. Ну что, сценарий для изучения теперь проще с Multitenant:
  1. Скачать новый APEX.
  2. Создать БД для тестирования:
    create pluggable database apx5 from tmpl file_name_convert( '/app/oracle/oradata/tmpl', '/app/oracle/oradata/apx5' );
  3. Установить свежий APEX 5.0 и посмотреть, что стало лучше, а что перестало работать. :)

Читать далее

среда, 15 апреля 2015 г.

Oracle Multitenant и ORA-28000

Наткнулся недавно на небольшую проблему — ORDS на Glassfish отказывался создавать подключения к БД, выводя на экран "503 — Service Unavailable" со следующим сообщением в server.log:
The pool named: apex is not correctly configured, error: ORA-28000: the account is locked


Посмотрел пользователя БД в файле конфигурации ORDS для пула apex ${configdir}/ords/conf/apex.xml:
...
<entry key="db.username">APEX_PUBLIC_USER</entry>
...

Настройки для соединения взял из ${configdir}/ords/defaults.xml:
...
<entry key="db.hostname">hostname</entry>
<entry key="db.port">1521</entry>
<entry key="db.servicename">pdb1.workgroup</entry>
...

Подсоединился к pdb1.workgroup, проверил пользователя APEX_PUBLIC_USER — открыт. И вот тут я потратил достаточно много времени, прежде чем вспомнил, что с появлением Multitenant Architecture в Oracle 12c появились общие пользователи. Переключился в корневую БД, и точно — заблокирован APEX_PUBLIC_USER!

alter user apex_public_user account unlock;
alter user apex_public_user identified by ...;

После этого ORDS смог подключиться, проблема была решена.

Читать далее

воскресенье, 22 февраля 2015 г.

Oracle APEX: разбивка на страницы интерактивных отчётов

Благодаря дискуссии на SQL.RU, решил проверить, как на самом деле происходит выдача страницы данных для интерактивного отчёта в Oracle APEX. Использовал версию 4.2.5, но не думаю, что что-то будет сильно отличаться вплоть до 4.1 включительно. Создал приложение с простым интерактивным отчётом, у которого в качестве источника данных был следующий запрос:

select * from emp

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

select {select list}
  from ( select {select list}, row_number() over( order by {ordering} ) apx$rn 
           from ( {filtering, computing etc.} ) 
          order by {ordering} )
 where apx$rn between :page_min_row and :page_max_row

Результаты отладки меня слегка удивили:


Была слабая надежда, что это не окончательный запрос, и где-то там его ещё дополнительно обернут… Однако, после поиска в исходниках и вдумчивого чтения разврапленного wwv_flow_worksheet.plb я обнаружил, что всё намного печальней: в WWV_FLOW_WORKSHEET.get_report открывается курсор по тексту запроса, в котором нет никакого намёка на первую и последнюю строки страницы. Вместо этого курсор в цикле вхолостую считывается, пока не доходит до первой строки страницы. Затем начинается вывод строк, пока не дойдёт до последней.

Какие из полученных знаний можно сделать выводы:
  1. Каждая следующая страница интерактивного отчёта, к которой перейдёт пользователь, будет требовать чтения всё большего объёма данных. Пользователей нужно учить пользоваться всеми инструментами ИО, такими как фильтры, сортировки и т.п., а не рассматривать его как большую решётку Excel, в которой вместо Page Down можно жать на ссылку к следующей странице отчёта.
  2. Пользоваться настройкой максимального отображаемого количества строк в интерактивных отчётах всё-таки необходимо. Собственно, этому и учит нас документация APEX и другие материалы, как теперь видно — обоснованно. В отличие от границ страницы, ограничение числа строк в текст запроса добавляется и влияет на план выполнения.
  3. Оптимизатор может решить выполнять Ваш тяжёлый запрос для отчёта в режиме ALL_ROWS, несмотря на необходимость для вывода на страницу всего лишь в первых паре сотен строк. Уговорить его этого не делать Вы сможете с трудом, например созданием дополнительного процесса Before Header, в котором будет выставляться явно соответствующий режим:
    execute immediate 'alter session set optimizer_mode = all_rows';
    Кроме того, в WWV_FLOW_WORKSHEET.get_worksheet_report_query при оборачивании текста запроса используется поле WWV_FLOW_WORKSHEETS.sql_hint, название которого намекает на возможное светлое будущее, где разработчику APEX предоставят интерфейс для указания хинтов запросу отчёта.

Читать далее