Тетрадочка DBA

Он идет!

Posted by shane54lv на 10 Июль, 2009

Не могу не поделиться — выцепил в Сети скудные обрывки фраз

Oracle 12g

Yes, you heard right. Oracle 12g is around the corner. There is not much information available on this new release. The only detail that leaked so far is that Oracle 12g won’t support raw filesystems anymore. This is bad news for RAC environments. The OCR and the voting disk relay on raw filesystems via CFS like OCFS.

The word is that ASM will step in and close the gap in 12g. Also, more emphasis on NFS will be placed as well.

Other than that, there’s not much information regarding functionality enhancements available. As soon as I get more details I will post it.

:)

Posted in Uncategorized | Отмечено: , , | Leave a Comment »

Хозяйке на заметку — SELECT … SAMPLE

Posted by shane54lv на 9 Июль, 2009

Навеяно постом Elic‘а из обсуждения «грубый count».

Узнал про интереснейшую фичу в Оракле. Есть возможность указать запросу SELECT прочитать лишь часть таблицы (sample) для того, чтобы получить примерный результат. Это нужно, например, чтобы узнать примерное количество строк в таблице. Если их там миллиард, понятно, что девятьсот миллионов или миллиард сто миллионов — разница не сильно большая, а вот count (*) будет работать сутки. Ну и т.д., примеров как это использовать можно придумать много.

Теория

Тип sample может быть как обычно, строки или блоки. Т.к. sample — это лишь предположение, результат от запроса к запросу всегда будет различаться, но можно заставить базу выдавать всегда одно и то же предположение — SEED.

И последнее. При использовании block sample, запрос обязательно должен идти через FTS или FFS. Если существует другой, более оптимальный путь, Оракл будет использовать его и вместо block sample результат будет выдан на основании row sample. Соответственно, чтобы форсировать block sample, необходимо хинтом указать использование фуллскана (хинт +FULL или +INDEX_FFS).

Практика

Берем таблицу KNS.KNS_LOG:

SELECT ROUND (t1.BYTES / 1024 / 1024 / 1024, 0) AS "Gb"
  FROM dba_segments t1
 WHERE t1.owner = 'KNS' AND t1.segment_name = 'KNS_LOG';

Результат — 28 Гб, самое то :) На продукции count(*) я запускать не стану, но зная количество блоков таблицы и скорость нашей подсистемы I/O (очень приличной, кстати), можно предположить, что работать будет долго. Точнее считать лень, да и не суть.

Теперь магия:

SELECT COUNT (1) * 10000 FROM kns.kns_log SAMPLE BLOCK (0.01);

Пояснение:

  • BLOCK (0.01) — используя блочную выборку, прочитать одну десятитысячную блоков таблицы
  • COUNT (1) * 10000 — соответственно, результат умножаем на десять тысяч

Запрос работает менее пол-секунды, результат 188 190 000. Повторные запуски:


188 190 000
153 360 000
149 630 000
129 950 000
229 950 000

Т.е. результат бросает из стороны в сторону очень значительное, в процентном отношении считать опять таки лень, но на глаз +/- 25%. Хотя это нормально для выборки 0.01% данных!

И последнее. Как я говорил выше, чтобы закрепить какое-то одно значение выборки, используем конструкцию SEED ():

SELECT COUNT (1) * 10000 FROM kns.kns_log SAMPLE BLOCK (0.01) SEED (5);

Число 5 — от балды, берем любую цифру, это просто константа для привязки результата запроса. Результат — 205 800 000 и при повторных выполнениях сохраняется, что и требовалось доказать.

И совсем последнее — проверка правильности результата:

SELECT * FROM dba_tables t1 WHERE t1.owner = 'KNS' AND t1.table_name = 'KNS_LOG';

Значение NUM_ROWS: 198 153 830 (статистика собиралась в воскресенье, два дня назад, после чего в понедельник работал джоб, подтирающий самые старые записи).

SELECT * FROM dba_indexes t1 WHERE t1.owner = 'KNS' AND t1.table_name = 'KNS_LOG';

Значение DISTINCT_KEYS для уникального индекса: 143 667 320.

Т.е. результаты запроса с SAMPLE похожи на правду.

Ссылка на доку: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i2065953

Posted in Uncategorized | Отмечено: , , , , , , , , | Leave a Comment »

Правильные опции команды «shutdown»

Posted by shane54lv на 8 Июнь, 2009

Коннор МакДоналд* как-то раз заметил, что Oracle’у следовало более аккуратно называть опции у команды shutdown, а именно:

  • shutdown abort‘ лучше называть ‘shutdown fast‘,
  • shutdown immediate‘ лучше называть ‘shutdown hopefully‘,
  • shutdown transactional‘ лучше называть ‘shutdown when hell freezes over‘,
  • а ‘shutdown normal‘ надо переименовать в ‘shutdown never‘.

Коннор МакДональд (Connor McDonald), основной автор, работает с Oracle с начала 1990-х годов. Он начинал работать с базой данных Oracle версий 6.0.36 и 7.0.12. За последние 11 лет он работал с системами в Австралии, Великобритании, Юго-Восточной Азии, Западной Европе и США. Коннор — член сети OakTable и хорошо известен как в кругах докладчиков на темы Oracle, так и в сетевых форумах по СУБД Oracle. Он поддерживает Web-сайт подсказок и советов (www.oracledba.co.uk), чтобы поделиться своим энтузиазмом в отношении Oracle и добиться более эффективного использования этой СУБД.

Posted in Uncategorized | 6 комментариев »

CPUApr2009

Posted by shane54lv на 27 Май, 2009

Памятка внукам — вырезки из 30+ страничного README файла по инсталляции патча CPUApr2009 — только «соль»:

  • Качаем с Металинка патч № 8290506 (инфа о всех доступных версиях патчах CPUApr2009 по платформам и версиям софта)
  • Создаем Restore Point (guaranteed / обычную), либо через Grid Control, либо вручную:

    SQL> CREATE RESTORE POINT "Before upgrade to CPUApr2009";
    SQL> CREATE RESTORE POINT "Before upgrade to CPUApr2009" GUARANTEE FLASHBACK DATABASE;
    
  • Выключаем в базе AUDIT — меняем значение параметра audit_trail на null (он статический).
  • Выключаем все — и базу, и ASM
  • Бекапим TAR’ом оба хоума — ASM + DB — и не забываем oraInventory
  • Выставляем ORACLE_HOME на ASM и по инструкции:

    unzip p8290506_10204_.zip
    cd 8290506
    opatch napply -skip_subset -skip_duplicate
    

    Если путь до opatch не прописан в PATH — пишем полный путь вызова:

    /u01/app/oracle/product/10.2.0/db/OPatch/opatch napply -skip_subset -skip_duplicate
    
  • Переключаем ORACLE_HOME на DB и повторяем предыдущий шаг.
  • Включаем ASM и по инструкции закачиваем необходимые скрипты в базу:

    cd $ORACLE_HOME/rdbms/admin
    sqlplus /nolog
    SQL> CONNECT / AS SYSDBA
    SQL> STARTUP
    SQL> @catbundle.sql cpu apply
    SQL> QUIT
    
  • Проверяем, не было ли ошибок: каталог $ORACLE_HOME/cfgtoollogs/catbundle содержит два файла вида:

    catbundle_CPU_[database SID]_APPLY_[TIMESTAMP].log
    catbundle_CPU_[database SID]_GENERATE_[TIMESTAMP].log
    
  • И последнее — перекомпилировать все, что развалидировалось.

      Проверка, выполнялась ли уже компиляция. Если запрос возвращает «no rows selected» — значит, ничего еще не делалось:

      SQL> SELECT *
             FROM registry$history
            WHERE ID = '6452863';
      
      no rows selected
      
      SQL>
      
      Предкомпиляционный скрипт — позволяет прикинуть, на сколько затянется компиляция и стоил ли ее делать сразу же, или maintenance window не на столько «широк» и компильнуть придется уже на рабочей системе:

      cd $ORACLE_HOME/cpu/view_recompile
      sqlplus /nolog
      SQL> CONNECT / AS SYSDBA
      SQL> @recompile_precheck_jan2008cpu.sql
      SQL> QUIT
      

      В моем случае результат был 18 119 объектов, требующих компиляции. Кстати, интересная деталь — я так и не понимаю, о каких объектах идет речь, т.к. запрос к DBA_OBJECTS на проверку всех объектов с полем STATUS != ‘VALID’ показывает 10-50 объектов, т.е. «это не они».

      Собственно, сама компиляция:

      cd $ORACLE_HOME/cpu/view_recompile
      sqlplus /nolog
      SQL> CONNECT / AS SYSDBA
      SQL> SHUTDOWN IMMEDIATE
      SQL> STARTUP UPGRADE
      SQL> @view_recompile_jan2008cpu.sql
      SQL> SHUTDOWN;
      SQL> STARTUP;
      SQL> QUIT
      

      У меня заняла около 30 минут и после работы осталось еще 12 000 нескомпилированных объектов. Они уже были видны через DBA_OBJECTS и для их компиляции используется стандартный скрипт utlrp.sql:

      cd $ORACLE_HOME/rdbms/admin
      sqlplus /nolog
      SQL> CONNECT / AS SYSDBA
      SQL> @utlrp.sql
      
  • Вот собственно и все. Процесс установки CPUApr2009 очень прост и прозрачен, нужно лишь заказать maintenance window не менее 2-х часов и расписать заранее все действия, чтобы ничего не забыть.

    Из оставшихся открытых вопросов:

    • Нужно ли патчить агента GC? Или поставить агента версии 10.2.0.5, судя по тому, что для большинства ОС он вышел совсем недавно, возможно он уже «пропатчен». Уточню.
    • Если создавалась гарантированная точка восстановления (глава 5.2 Using Normal and Guaranteed Restore Points из книги Oracle® Database Backup and Recovery Basics 10g Release 2 (10.2)), необходимо внимательно следить за местом во FRA, используемом для обеспечения возможности восстановления:
      SELECT NAME, TIME,
             ROUND (storage_size / 1024 / 1024 / 1024, 0) AS "Storage Size, Gb"
        FROM v$restore_point;
      

      В моем случае, после установки патча в базу и компиляции объектов, запрос возвращал около 3 Гб; после запуска апликации и 30 минут работы (ночь, но работают ночные задания), размер вырос до 16 Гб. После чего я принял решение, раз все работает — точку восстановления стереть:

      SQL> DROP RESTORE POINT "Before upgrade to CPUApr2009";
      

Posted in Решение проблем | Отмечено: , , | Leave a Comment »

Пара ссыл по APEX’у и не только

Posted by shane54lv на 22 Май, 2009

Очередная подборка, разделю ее на четыре части: APEX, Java, Oracle и что-то еще. Поехали.

APEX:

  • Блог человека по имени Патрик Вульфт — видимо, авторитетен в области.
  • Некто Денес Кубичек (да-да, ДенЕс), примеры всяких фишечек (не блог а хрен знает что, просто свалка решений).

Дальше — Java:

Теперь очередь Oracle:

И пара ссыл не в тему:

Posted in URL'ы | Отмечено: , , , , , , | 1 Comment »

Задача «WF clean»

Posted by shane54lv на 22 Май, 2009

Какие-то запросы из той задачи:

SELECT   item_type, COUNT (item_key)
    FROM applsys.wf_items
GROUP BY item_type;

SELECT t1.segment_name, ROUND (t1.BYTES / 1024 / 1024, 0) AS "Mb"
  FROM dba_segments t1
 WHERE t1.owner = 'APPLSYS'
   AND t1.segment_name IN
          ('WF_ITEMS',
           'WF_ITEM_ACTIVITY_STATUSES',
           'WF_ITEM_ACTIVITY_STATUSES_H',
           'WF_NOTIFICATIONS',
           'WF_NOTIFICATION_ATTRIBUTES',
           'WF_COMMENTS',
           'WF_ITEM_ATTRIBUTE_VALUES',
           'WF_DIG_SIGS'
          );

SELECT COUNT (item_key)
  FROM apps.wf_items
 WHERE item_type = 'WFERROR';

SELECT COUNT (*)
  FROM applsys.wf_items
 WHERE item_type = 'WFERROR';

SELECT COUNT (*)
  FROM applsys.wf_items
 WHERE TRUNC (end_date) = TO_DATE ('13.06.2008', 'dd.mm.yyyy');

SELECT *
  FROM dba_indexes t1
 WHERE t1.owner = 'APPLSYS'
   AND t1.status != 'VALID'
   AND t1.table_name IN
          ('WF_ITEMS',
           'WF_ITEM_ACTIVITY_STATUSES',
           'WF_ITEM_ACTIVITY_STATUSES_H',
           'WF_NOTIFICATIONS',
           'WF_NOTIFICATION_ATTRIBUTES',
           'WF_COMMENTS',
           'WF_ITEM_ATTRIBUTE_VALUES',
           'WF_DIG_SIGS'
          )

Posted in Query'ы | Отмечено: , , , | Leave a Comment »

Проблемы инсталляции GC агента 10.2.0.5 на SuSE 10 x86-64

Posted by shane54lv на 22 Май, 2009

Ставлю агент GC за версией 10.2.0.5 на SuSE 10 x86-64 и получаю ошибку:


INFO: Exception thrown from action: make
Exception Name: MakefileException
Exception String: Error in invoking target 'client_sharedlib' of makefile '/u01/app/oracle/product/agent10g/network/lib/ins_net_client.mk'. See '/opt/oracle/oraInventory/logs/installActions2009-05-22_08-10-10PM.log' for details.
Exception Severity: 1

Документ Note: 365655.1 — Problem: Linux64: Agent Installation Fails with Linking Error ‘cannot open crti.o: No such file or directory ‘ предлагает поставить 32-битную версию RPM’а glibc-devel-2.3.2-95.39.i386 (лежит, кстати, тут). Вся эта история странная, т.к. на нескольких серверах уже стоит агент 10.2.0.5 и проблем при инсталляции не было. Правда, детальный осмотр ситуации показал, что отличаются цифры ядер линуксов. Буду копать-с.

Posted in OS'ы | Отмечено: , , , , , , , | Leave a Comment »

Ссылки: управление проектами

Posted by shane54lv на 22 Май, 2009

Подборка ссылок об управлении проектами:

Все эти ссылки я планомерно шлю своему главному менеджеру проектов, называя этот процесс «Володя, я делаю из тебя человека» :)

P.S. Володя — это тот самый менеджер.

Posted in URL'ы | Отмечено: , , | 2 комментария »

Grid Control кричит «UNDO TBS full» — без паники

Posted by shane54lv на 22 Май, 2009

Опять стреманул, пошли сообщения UNDOTBS1 is 99% full. Почитал – все спокойно, это нормально для 10gR2 при AUTOEXTEND=OFF для UNDO:

Цитата:


The Undo Block allocation algorithm in Automatic Undo Management is the following :

1. If the current extent has more free blocks then the next free block is allocated.
2. Otherwise, if the next extent expired then wrap in the next extent and return the first block.
3. If the next extent does not expired then get space from the UNDO tablespace. If a free extent is available then allocate it to the transaction table and return the first block in the new extent.
4. If there is no free extent available then steal from an offline transaction table. Deallocate the extent from the offline transaction table and add it to the current transaction table. Return the first free block of the extent.
5. Steal from online transaction table. Deallocate the extent from the online transaction table and add it to the current transaction table. Return the first free block of the extent.
6. Extend the file in the UNDO tablespace. If the file can be extended then add an extent to the current transaction table then return the block.
7. Otherwise try to reuse unexpired extents from own transaction table. If all extents are currently busy(they contains uncommitted information) go to the step 8. Otherwise wrap into the next extent.
8. Steal unexpired extents from offline transaction tables. If this fails then try on online transaction tables.
9. If all the above fails then return ORA-30036 unable to extend segment by %s in undo tablespace ‘%s’

When the UNDO tablespace is created with NO AUTOEXTEND, following the allocation algorithm, here is the explanation for this correct behavior:

For a fixed size UNDO tablespace (NO AUTOEXTEND), starting with 10.2, we provide max retention given the fixed undo space, which is set to a value based on the UNDO tablespace size.
This means that even if the undo_retention is set to a number of seconds (900 default), the fixed UNDO tablespace supports a bigger undo_retention time interval (e.g: 36 hours), based on the tablespace size, thing that makes the undo extents to be UNEXPIRED. But this doesn’t indicate that there are no available undo extents when a transaction will be run in the database, as the UNEXPIRED undo segments will be reused.
Solution

This is a correct behavior, concerning an UNDO tablespace created with AUTOEXTEND OFF in 10gR2, so there is not need to add more space to it or be concerned by the fact that it appears to be 100% full.

Надоест – ставим всем датафайлам UNDO autoextend = on при текущем размере, чтобы расти было некуда (наебка короче) – все, Automatic Undo начинает работать по-другому и ошибок таких не будет. И пару SQL:

SELECT *
  FROM dba_undo_extents;

SELECT COUNT (*)
  FROM dba_undo_extents t1
 WHERE t1.status = 'UNEXPIRED';

SELECT COUNT (status)
  FROM dba_undo_extents
 WHERE status = 'EXPIRED';

SELECT COUNT (status)
  FROM dba_undo_extents
 WHERE status = 'ACTIVE';

SELECT DISTINCT t1.tablespace_name
           FROM dba_free_space t1
       ORDER BY 1 DESC;
where t1.tablespace_name = 'UNDOTBS1';

SELECT t1.tablespace_name, t1.BYTES / 1024 / 1024
  FROM dba_free_space t1
 WHERE t1.tablespace_name = 'UNDOTBS1';

SELECT creation_time, metric_value, MESSAGE_TYPE, reason, suggested_action
  FROM dba_outstanding_alerts
 WHERE object_name = 'UNDOTBS1';
 
SELECT creation_time, metric_value, MESSAGE_TYPE, reason, suggested_action,
       resolution
  FROM dba_alert_history
 WHERE object_name = 'UNDOTBS1';
 
SELECT object_type, object_name, warning_value, critical_value
  FROM dba_thresholds
 WHERE object_type = 'TABLESPACE';

SELECT   (  (SELECT (NVL (SUM (BYTES), 0))
               FROM dba_undo_extents
              WHERE tablespace_name = 'UNDOTBS1'
                AND status IN ('ACTIVE', 'UNEXPIRED'))
          * 100
         )
       / (SELECT SUM (BYTES)
            FROM dba_data_files
           WHERE tablespace_name = 'UNDOTBS1') "PCT_INUSE"
  FROM DUAL;

SELECT *
  FROM v$undostat;

Posted in Query'ы, URL'ы | Отмечено: , , , , , , , , | 1 Comment »

Настраиваю аудит

Posted by shane54lv на 22 Май, 2009

Включаем все что можно для отлова всех DDL:

audit alter system, cluster, context, database link, dimension, directory, index, materialized view, procedure, profile, public database link,
      public synonym, role, rollback segment, sequence, synonym, system audit, system grant, table,  tablespace, trigger, type, user, view;

audit alter sequence, alter table, comment table, grant directory, grant procedure, grant sequence, grant table, grant type;

Смотрим, что включено:

SELECT audit_option, success, failure
 FROM dba_stmt_audit_opts;

Смотрим напрямую в AUD$:

SELECT t1.*
 FROM dba_audit_trail t1;

SELECT COUNT (1)
 FROM dba_audit_trail;

И если что – чистим:

truncate table sys.aud$;

DELETE FROM aud$
WHERE TRUNC (ntimestamp#) < TO_DATE ('01-07-2009', 'DD-MM-YYYY'); [/sourcecode] Какие бывают AUDIT ACTION’s: [sourcecode language="sql"] SELECT * FROM audit_actions; [/sourcecode] Вьюшка для FGA и комбинированная, для FGA и обычного аудита: [sourcecode language="sql"] SELECT * FROM dba_fga_audit_trail; SELECT * FROM dba_common_audit_trail; [/sourcecode] Ну и запрос для анализа аудита: [sourcecode language="sql"] SELECT TO_CHAR (t1.TIMESTAMP, 'DD Mon YYYY HH24:MI') AS "Timestamp", t1.username, t1.userhost, t1.os_username, t1.owner, t1.obj_name, t1.action_name, t1.ses_actions FROM dba_audit_trail t1 WHERE t1.obj_name NOT LIKE 'KNS_%_TMP' -- system activity AND t1.obj_name NOT LIKE 'EUL4_%' -- system activity AND t1.obj_name != 'KNS_PAP_DIR' -- system activity AND t1.obj_name != 'PAP_DB_DIRECTORY' -- system activity AND TRUNC (t1.TIMESTAMP) = TO_DATE ('06-07-2009', 'DD-MM-YYYY') ORDER BY "Timestamp" DESC; SELECT a.userid, a.STATEMENT, a.obj$name, a.userid, a.ses$actions, a."NTIMESTAMP#", b.NAME, sqltext FROM SYS.aud$ a, SYS.audit_actions b WHERE a."ACTION#" = b.action; SELECT t1.owner, t1.segment_name, ROUND (t1.BYTES / 1024 / 1024, 0) AS "Mb" FROM dba_segments t1 WHERE t1.owner = 'SYS' AND t1.segment_name = 'AUD$'; [/sourcecode]

Posted in Query'ы | Отмечено: , | Leave a Comment »