Dsvolk > > Oracle > > Faq > > Dba
Dsvolk > > Oracle > > Faq > > Dba My Blog | Search | About
(Not Logged In)
[ welcome! ] [ news ] [ install ] [ jump-jet ] [ app ] [ rac ] [ papers ] [ dba ] [ dvp ] [ racdd4d ] [ oem ] [ statspack ] [ education ] [ tuning ] [ ias ] [ backup ] [ dataprotection ] [ security ] [ oid ] [ options ] [ integration ] [ sales ] [ sun ] [ linux ] [ consulting ] [ faq ]

ЧАВО

Соглашение о материалах на этом сайте

Мой oracle blog
true dsvolk!
ЧАсто задаваемые ВОпросы  
 

DBA      

Очень рекомендую установить себе Remote Diagnostic Agent. Результаты ее работы могу существенно сократить время на изучение Вашей конфигурации.

 

NT

 

 

 

Links:

www.ixora.com.au

tahiti.oracle.com

asktom.oracle.com

metalink.oracle.com

otn.oracle.com

hotsos.com

jlcomp.demon.co.uk

www.orafaq.net

oraperf.sourceforge.net


Q: Как найти блокировки в БД и что они означают ?

A: Умные люди (aka metalink) все написали. Сам скрипт можно взять здесь. Есть конечно еще масса способов типа dba_dml_locks, dba_ddl_locks но мне они кажутся менее удобными.

Если сделать запрос вида: select * from test for update то вывод скрипта будет такой: 

Username    SID Term   Table Name COMMAND          Lock Held       Lock Requested       ID1 - ID2    Lock Type
---------- ---- ------ ---------- ------------------------------- -------------------- ------------- ---------
ET           12 pts/3  None       BACKGROUND       Row Share       NONE                 43773-0       TM 
                       None       BACKGROUND       Exclusive       NONE                 262183-6210   TX 

чтобы  достать имя объекта нужно  сделать запрос вида:

 SQL>  select owner#, name from  sys.obj$  where obj# = 43773;

    OWNER# NAME
---------- ------------------------------
        41 TEST

 где 43773 чиселка = id1 от TM лока.  Если есть взаимная блокировка то имя  таблицы для ожидающей сессии показывается сразу.  

Q: Что делать если я случайно удалил datafile  ?

A: Остается перестартовать базу в состояние mount (когда файлы еще не открываются), удалить файл alter database datafile ... offline drop. И открыть базу. Прочитать оригинал можно здесь. Табличное пространство там удаляется так как Oracle продолжает хранить информацию о датафайле даже если Вы его удалили..

Выдержка 

SVRMGR> startup nomount; -- step 1, startup nomount.. 

ORACLE instance started. 

Total System Global Area 11999664 bytes 

Fixed Size 51632 bytes 

Variable Size 7364608 bytes 

Database Buffers 4505600 bytes 

Redo Buffers 77824 bytes 

SVRMGR> alter database mount; -- step 2, mount the database 

Statement processed. 

SVRMGR> alter database datafile '/tmp/test.dbf' offline drop; 

Statement processed. -- step 3, get rid of the offending file 

SVRMGR> alter database open; -- your database will open now 

Statement processed. 

SVRMGR> drop tablespace test including contents; 

Q: Как удалить  datafile  ?

A: Формально, удалить файл из Oracle без удаления табличного пространства нельзя. Однаков, если вы его добавили только что и по ошибке, то лучше всего сразу сжать его до минимального размера, скажем несколько блоков. Подробнее

Q: Что делать если удалил rollback tablespace  ?

A: Это мне кажется не страшно. Если база лежит - с большой вероятностью все получиться. Если база в archive log - то  же все хорошо. Важно вынести из init.ora упоминание rollback segment ов. Ведь 1 жизненно важный сегмент всегда в system находится...

Все ситуации подробно расписаны на metalink. Там же и про секретный параметр _corrupted_rollback_segments пишут.

Вот только что делать для undo tablespace ? ума не приложу :(( 

Q: Где взять патчи и какие они есть на текущий момент ?

A: Текущие патчи собраны на странице http://otn.oracle.com/support/patches.htm

Если у Вас есть доступ к патчам, то в Вашем профиле в metalink слева есть соответствующая кнопочка.

Некоторые номера:

ID:1797444 Patchset::2376472
8.1.7.4 PATCH SET FOR ORACLE DATA SERVER
Product:Oracle Database
Platform:MS Windows NT/2000/XP Server

Q: Как включить аудит ?

A: Для того чтобы включить аудит нужно установить параметр audit_trail в ;

  • OS - тогда запись будет идти в файл на операционной системе

  • DB - тогда в таблицу sys.aud$

Для того чтобы указать файл, куда должны попадать события аудита используется параметр AUDIT_FILE_DEST.  Windows не использует этот параметр, а пишет события в Event Viewer.

Из опыта известно что если аудит идет в таблицу БД то system tablespace быстро переполняется. Поэтому рекомендуют править скрипт cataudit.sql чтобы изменить табличное пространство в нем.

Остается настраивать какие операции вы хотите наблюдать. Читать для версии 8.1.7 или мою статью "включаем аудит".

В init.ora 

audit_trail=OS
audit_file_dest='/var/oracle/audit'

mkdir /var/oracle/audit

При этом, в директории audit_file_dest будут появляется файлы с audit информацией. Информация о подключении к БД в режиме internal попадает в директорию $ORACLE_HOME/rdbms/audit/

В 9i появился параметр transaction_auditing = false по умолчанию. В документации написано что "Oracle generates a special redo record that contains the user logon name, username, the session ID, some operating system information, and client information. For each successive transaction, Oracle generates a record that contains only the session ID. These subsequent records link back to the first record, which also contains the session ID. These records might be useful if you are using a redo log analysis tool. You can access the records by dumping the redo log."

Q: Что такое pctfree и pctused ?

A:  Эти два параметра устанавливаются на уровне таблицы и отвечают за управление свободным местом внутри блока. Их значение устанавливаются в процентах и в сумме не могут превосходить 100.

PCTFREE говорит, сколько места следует оставить под будущие update записей в таблице. Если PCTFREE = 10, то после того как 90% места в блоке будет занято, Oracle начнет помещать записи в новый блок.

PCTUSED говорит о том, когда блок следует помещать в список свободных блоков (freelist). Так значение 40, говорит что когда в блоке окажется более 60% свободного места, то он может быть помещен во freelist.

Таким образом, если у Вас приложение активно добавляет новые записи, и удаляет старые и проблема с освобождением места для Вас актуальна,  то оптимальным для Вас являются значения pctfree = 1, pctused = 99. Очевидно это может принести некоторую деградацию производительности. Следует следить за freelist latch contention.

Что делать если Вы изначально не угадали с этими параметрами. Во первых 

SQL> alter table test pctfree 1 pctused 99;

Эти параметры начнут действовать сразу, как только вы попытаетесь скажем удалить запись. Но пока Вы  не удалите запись из блок он  во freelist сам не попадет. Это происходит потому, что Oracle инспектирует блоки только когда ему необходимо добавить-удалить записи. Но freelist не перестраиваться сам даже при перестройке таблицы (alter table move). Т.е. со старыми блоками не понятно что делать.  Есть хакерский прием - удалить записи, потом откатить изменения - free list перестроиться (!)  - но это конечно странный метод. Сейчас ищу другой ..

Замечательная ссылка на фирменную документацию с картинками. 

Вот как я тестировал что происходит. Сначала ставим неправильное значение pctused=20, потом исправляемся и смотрим при разных шаманских действиях типа alter table move что произошло. Пакет dba_utils можно взять здесь

drop table test;
create table test (n integer, c char(2000) default '*') pctfree 10 pctused 20;
set serveroutput on;
exec dba_utils.show_space ('TEST');
insert into test (n) select rownum from all_users where rownum < 51;
exec dba_utils.show_space ('TEST');
alter table test pctfree 1 pctused 99;

Q: Как оценить насколько оптимально выбраны параметры pctfree и pctused ?

A:  Проанализируйте свою схему (ниже используется в качестве примера схема SMAP) простым способом 

sqlplus sys/manager 

SQL> alter session set sort_area_size = 5120000;

Простой способ:

SQL>exec dbms_stats.GATHER_SCHEMA_STATS ('SMAP');

или чуть более сложным:

begin
dbms_stats.gather_schema_stats (ownname =>'SMAP', estimate_percent
=> 90, block_sample => TRUE, method_opt => 'for all indexed columns');
end;
/

Здесь может возникать ошибка 

unable to extend temp segment by 64 in tablespace TEMP

Тогда следует попробовать увеличить sort_area_size и (или) размер next для TEMP.

Узнайте свой db_block_size 

SQL> select value from v$parameter where name = 'db_block_size';

и запустите следующий скрипт  (используется предположение что db_block_size = 8192

sqlplus smap/smap

SQL>select sum( (num_rows*AVG_ROW_LEN)) must_be_used, sum((blocks*8192 - AVG_SPACE_FREELIST_BLOCKS)) used from user_tables;

Общий смысл его таков - я сравниваю место которое должны были бы занимать данные без учета накладных расходов на заголовки блоков, с тем свободным местом которое осталось в уже использованных блоках, которым удалось попасть во free list. Т.е. разница - это место в блоках, которые не попали во freelist и накладные расходы. Если расхождение велико - мне кажется что это говорит о неэффективном использовании места. Это может быть как неудачно выбранные методы хранения так и параметры pctfree, pctused

Q:  Как предотвратить ORA-0165x, ORA-1688 : Unable to Extend < OBJECT > by %S in Tablespace %S ?

A:  Для того чтобы узнать о будущих возможных проблемах с extent'ами используйте следующий скрипт. Выполняйте его как пользователь sys. Он делает 2 вещи:

  • Показывает каким объектам не удастся захватить себе следующий extent.

  • Показывает какие объекты достигли своего максимального числа extent'ов

Нужно понимать, что ситуация когда обеъкт не может захватить себе следующий extent является поводом задуматься - на сколько времени хватит последнего (текущего) extent'а. От это и зависит с какой частотой запускать этот скрипт. Я обычно запускаю его раз в сутки.

Что делать если в увидели в списке объекты. Либо что то удалить из их табличного пространства или добавить новый datafile, или расширить существующий. Детальное описание на metalink.

Q:  Что делать с ошибкой ORA-3232 ? (обновлен 16.10.2003 )

A:  Эта ошибка случается когда запрос выполняется используя hash join и неверно выставлены параметры temp tablespace.

Мне кажется что на платформе Sun, это не происходит, вот на Linux - пожалуйста. Хотя написано, что он вычисляется, похоже что это иногда не происходит. Вот что нужно делать: Надо поставить параметр hash_multiblock_io_count < размера next из табличного пространства TEMP. Или увеличить размеры initial и next для TEMP.

Посмотреть значение параметра  hash_multiblock_io_count можно так 

oracle@alpha:~/RCO40/installation} sqlplus sys/manager

Узнаем имя табличного пространства (цифра 2 была в тексте ошибки) 

SQL> select name from sys.ts$ where ts# = 2;

NAME

------------------------------

TEMP

 

 

А размеры initila и next так 

SQL> select initial_extent, next_extent from dba_tablespaces where tablespace_name = 'TEMP';

INITIAL_EXTENT NEXT_EXTENT
-------------- -----------
16384 16384

 

 

SQL> show parameter hash_multiblock_io_count

16

Hash_multiblock_io_count  правда измеряется в блоках.

Поменять размеры extent для temp можно так:

alter tablespace temp default storage (initial 1032192 next 1032192);

Оригинальная статья металинка

Кирилл Викторов утверждает что все вышеперечисленное встречается и справедливо для платформы Sun. 

Есть рекомендация выставлять Hash_multiblock_io_count  по формуле такая (MAX_IO_SIZE/DB_BLOCK_SIZE) - 1, что  для Линукса дает нам (65,536/<Parameter:DB_BLOCK_SIZE>) - 1. Таким образом, значение hash_multiblock_io_count должно быть равно 7 при db_block_size = 8192. 

On Windows NT, MAX_IO_SIZE is set to 64 KB - 512, or 65012 bytes говориться в документации к 8.0.3.

Читать про MAX_IO_SIZE отдельно.

Q:  Как происходят сортировки ?

A:  Все о том как происходят сортировки написано в статье металинка.

От себя могу добавить важную вещь - обратите внимание чтобы параметр sort_area_size был не больше чем размер extent'а во врменном табличном пространстве. Вот формула 

(n*s + b) with

n = positive integer,

s = value of SORT_AREA_SIZE initialization parameter, and

b = value of DB_BLOCK_SIZE initialization parameter.

В противном случае при переходе к сортировке на диске возникнет ошибка.

Поменять размеры extent для temp можно так:

alter tablespace temp default storage (initial 1032192 next 1032192);

Q:  Как перенести данные между версиями моей системы  ?

A: C помощью export/import и нескольких полезных скриптов

  1. Выгрузить схему с помощью команлы exp:- данные(rows=Y) без индексов(indexes=N), с сжатием сегментов (compress = Y)

  2. Создать новую схему в новых табличных пространствах. Схема не должна содержать справочной информации !. 

  3. Отключить все констрейнты и триггера. (см disable_all_constraints.sql в dba_utils.tar)

  4. Подумайте, или просто посмотрите (grep -ni grants my.dmp) какие привилегии будут выдаваться при импорте. Создайте недостающие роли и или пользователей. Выполнить загрузку  старых данных с помощью команды imp, игнорируя произошедшие ошибки (ignore=Y)

  5. Если это надо, удалить старые справочники, закачать новые. 

  6. Включить все триггера и констрейнты проверить, что все включилось (enable_all_constraints.sql в dba_utils.tar). 

Q:  Как настроить MTS ?

A:  В init<SID>.ora надо написать 

MTS_DISPATCHERS = "TCP,3"
MTS_SERVERS=1
MTS_MAX_DISPATCHERS=6
MTS_MAX_SERVERS=3
MTS_SERVICE = DVP
MTS_LISTENER_ADDRESS="(ADDRESS=(PROTOCOL=TCP)(HOST = alpha.service.jet.msk.su)(PORT = 1521))"

В listener.ora 

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = alpha.service.jet.msk.su)(PORT = 1521))
)
)

Контролировать сколько каких соединений можно командой:

lsnrctl services 

В 9i параметры MTS_* изменили свои имена, но пользоваться старыми все еще можно.

Более подробно см статью metalink .

Q:  Как установить JVM в 8.1.7 ?

A:  Нужно выполнить скрипт @?/javavm/install/initjvm.sql. Но !

Перед его запуском нужно проверить что: 

  1. В system есть 150M свободных.

  2. В rbs есть 250 M свободных

  3. java_pool_size > 30M.

  4. в shared_pool_size есть 60M свободных.

Часто, по крайне мере у меня, с первого раза этот скрипт не проходит именно из-за недостатка системных (oracle) ресурсов. Надо выяснить чего не хватило, исправить. Запустить  скрипт удаления rmjvm.sql. И только после этого продолжать. Если Вам показалось, что все пршло успешно, выполните следующий select 

SQL>select count(*) from dba_objects where object_type like 'JAVA%' and

status = 'INVALID' and owner = 'SYS';

 

COUNT(*)

----------

0

Полностью статья металинка

Q:  Когда нужно перестраивать индексы ? (обновлено 02.06.2003 )

A: Ниже я обсуждаю нормальные B-tree индексы и dictionary managed tablespace.

Мне кажется, что в двух случаях:

  1. Когда кол-во extent ов индекса больше скажем 10. Это примитивно влияет на производительность. Миф это или нет, мне понять сложно. Я видел, что да, влияет на уровне версий Oracle 7-8.0. Так мне показалось, по крайне мере. Здесь большая дискуссия на эту тему. Mark Gurry считает, что да, кол-во extent'ов влияет. Tom Kyte - что до числа 1024 и особенное если это индексы - не влияет. Статья о дефрагментации вообще. Есть и более простые соображения. Если у Вас OLTP приложение, то нужно избегать вынужденного (т.е. выполняемого сервером самостоятельно по необходимости) выделения extent'ов.  Это общая рекомендация вне зависимости от типа segment'а. В 8i и 9i рекомендуется использовать local-managed tablespaces. Тогда мне кажется, вся дискуссия о количестве сегментов действительно не так важно. В заключение, ИМХО: Если Oracle сделал новый тип управления местом в табличных пространствах и  полностью, включая system tablespace перешел на его использование, значит старый способ был не вполне хорош. 

  2. Когда много и часто удалялись и добавлялись записи. Здесь дело в том, что Oracle не освобождает индексные блоки содержащие удаленные записи. Удаленные индексные записи могут быть использованы еще раз, только если в таблице появиться соответсвующая запись. Поэтому индекс может только увеличиваться в объеме в течении своей жизни.  Это называется естественной деградацией.

Если в первом случае все достаточно понятно: 

col segment_name format a20;

select SEGMENT_NAME, count(*) from user_extents where segment_type = 'INDEX' 
having count(*) > 10 group by segment_name;

То во втором есть некоторая путаница среди гуру. Так Tom Kyte уверяет, что перестройка индексов из-за их естественной деградации - пустое занятие. Но хитрые индусы из металинка все таки дают нам следующий совет: 

  1. Проанализируйте индексы с помощью команды 
    ANALYZE INDEX &index_name VALIDATE STRUCTURE; 

  2. Вычислите отношение удаленных записей в индексе к существующим. И если это отношение велико (> 20%), то перестройте индекс с помощью команды: 
    ANALYZE INDEX &index_name REBUID;

 Эти советы я собрал в скрипт index_analyze.sql

См. также дискуссию в конференции:  http://talk.mail.ru/thread_article.html?ID=25912375

Jonathan Lewis - Unbalanced Indexes ?

metalink - Guidelines on When to Rebuild a B-Tree 

The Internal Structure of Indexes

Q:  Почему в моей БД не освобождается место  ?

A: Вернее так, почему при удалении записей не освобождается место и  приложение не работает быстрее ?

А Вы Recycle bin давно чистили ? :))) Шутка. 

Действительно то, что при удалении записей во view dba_free_space ничего не меняется. (см free_space.sql) часто сбивает с толку людей. Но это верно, поскольку даже после удаления всех записей в таблице считается, что таблица аллокировала все свои extentы и это место свободным не считается. 

Можно узнать сколько места реально занимают индексы и таблицы, например с помощью процедуры dba_utils.show_space. И вот тут нас будет ждать первый сюрприз - индексы не уменьшились в размерах даже после удаления записей ! Оказывается Oracle не удаляет вхождения записей из индексов, а лишь помечает их как удаленные. Чтобы реально увидеть сколь места стал занимать индекс его нужно перестроить. Читайте когда и как перестраиваются индексы.  

Ой ! А почему я удалил несколько записей, а show_space показывает все тоже что и до удаления ? Это скорее всего связано с параметрами pctfree и pctused. Читайте что это и как оценить их эффективность.

Почему же наше приложение не ускорилось после удаления записей ?. Оказывается, если приложение использует full scan, то даже после удаления записей Oracle прочитывает все блоки (даже пустые!) до границы HWM - верхней границы которой когда либо достигала таблица. Здесь остается надеяться на использование индексов или перестройку таблиц. 

Храните информацию в  LOB segment'ах ?. Вы их используете ? Читайте как Oracle освобождает место после удаления LOB объектов.

Используете полнотекстовый поиск ? А индекс кто будет перестраивать ?

Q:  Как оценить размер полнотекcтового индекса ?

A:  Действительно, полнотектовый индекс представляет собой другой тип индексов, в отличии от скажем B- Tree. Собственно этот индекс состоит из нескольких объектов и поэтому нужно суммировать их размер.

Оценить его размер лучше всего с помощью процедуры context_index_size пакета dba_utils. Определим сначала какие индексы у Вас являются полнотекстовыми: 

SQL> select index_name from user_indexes where index_type = 'DOMAIN';

INDEX_NAME
------------------------------
TEXT_PART_I

Теперь посмотрим его размер:

SQL> set serveroutput on;
SQL> exec dba_utils.context_index_size ('TEXT_PART_I', USER);
============================================================
Space usage of Text Index: SMAP13.TEXT_PART_I
============================================================
TABLE_NAME = DR$TEXT_PART_I$I
TABLESPACE NAME = SMAP13_DICT
ALLOCATED BLOCKS = 13
ALLOCATED BYTES = 106,496 ( 0.10Mb)
USED BLOCKS = 11
USED BYTES = 90,112 ( 0.09Mb)
------------------------------------------------------------
TABLE_NAME = DR$TEXT_PART_I$R
TABLESPACE NAME = SMAP13_DICT
ALLOCATED BLOCKS = 13
ALLOCATED BYTES = 106,496 ( 0.10Mb)
USED BLOCKS = 2
USED BYTES = 16,384 ( 0.02Mb)
------------------------------------------------------------
============================================================
TOTAL ALLOCATED BLOCKS = 26
TOTAL ALLOCATED BYTES = 212,992 ( 0.20Mb)
TOTAL USED BLOCKS = 13
TOTAL USED BYTES = 106,496 ( 0.10Mb)

 

Теперь наше естественное желание уменьшить размер индекса. Если можно его перестроить - то перестроить. Но это может быть очень, очень долго. Тогда можно его оптимизировать.

SQL> exec ctx_ddl.optimize_index ('TEXT_PART_I', 'FULL');

Далее зайти пользователем ctxsys/ctxsys и просмотреть результаты оптимизации:

col idx_opt_token format a20

select idx_name,idx_opt_token,idx_opt_type,idx_opt_count from dr$index;

В документации написано что эта процедура оптимизирует не более 16,000 записей за запуск. Т.е. ее необходимо будет повторять до опупения :(( Еще про оптимизацию и перестройку контекстных индексов 

Q:  Зачем и как устанавливать параметр  OPTIMAL  для rollback segment'ов?

A:  Параметр OPTIMAL показывает к какому значению будет сжиматься rollback segment после своего разбухания. Но, важно понимать, когда это происходит. Когда  транзакция  захватывает новый экстент, проверяется нет ли возможности осуществить сжатие rollback segment. И если да, то это происходит. Этот процесс может занимать существенное время и ресурсы. Но он необходим, что один из сегментов не занял все пространство rbs tablespace.  Мне кажется, что для установки OPTIMAL либо надо знать размеры ваших транзакций, либо просто поделить размер rbs на кол-во rollback segment'ов. Итак, устанавливать значение optimal нужно, но его необходимо грамотно выбирать. Слишком маленькие значение приведет к потере производительности, слишком большое - к нерациональному использованию места в rbs, а иногда и к его нехватке. 

Ниже показано как посмотреть текущие установки (optimal)  и сравнить их с максимальным размером rollback segmenta (hwmsize)

SQL> select usn, wraps, optsize, hwmsize from v$rollstat;

USN WRAPS OPTSIZE HWMSIZE
---------- ---------- ---------- ----------
0   0 745472
1   0 4194304 5234688
2   0 4194304 4710400
3   0 4194304 4710400
4   0 4194304 4710400
5   0 4194304 4710400
6   0 4194304 4710400
7   0 4194304 4710400

Q:  Как рассчитать кол-во rollback segment'ов для БД?   (создан 07.05.2003, автор  Алексей Рощин)

A:  Для 8i или 9i с undo_managment = manual. 

Oracle рассчитывает нужно число сегментов по формуле TRANSACTIONS / TRANSACTIONS_PER_ROLLBACK_SEGMENT

TRANSACTIONS - это максимальное число одновременных транзакций. 

TRANSACTIONS_PER_ROLLBACK_SEGMENT - Число одновременных транзакций, разрешаемое на сегмент отката

Есть два исключения из этого правила. 

  1. Результат должен быть округлен вверх до ближайшего числа, делящегося на 4 без остатка. Т.е. если получилось 6 - округляем до  8.  

  2. Oracle не рекомендует делать более 50  rollback segment'ов одновременно. 

 Если установлен параметр rollback_segments, то Oracle использует перечисленные там имена, а если их общие количество оказалось меньше, чем в вышеприведенной формуле, то добавляет по своему разумению до нужного числа. Добавлять Oracle может из списка тех, которые были созданы с помощью команды CREATE PUBLIC ROLLBACK SEGMENT. Если необходимые  public rollback segments были в offline, то oracle переведет их в online принудительно (!).  Если же таких оказалось меньше, чем рассчитал Oracle, то ничего не сделаешь - так их и будет меньше. Сами они не создаются.

Если параметр TRANSACTION не установлен явно, то он вычисляется по формуле = SESSIONS*1.1

SESSIONS в свою очередь определяется как (1.1 * PROCESSES) + 5 (Static, Integer). Параметр SESSIONS определяет максимальное число сессией, которые могут быть созданы в системе. Вы должны устанавливать этот параметр равным максимальному числу одновременно работающих пользователей +  число фоновых процессов + 10% на рекурсивные сессии. Описание параметра на metalink

PROCESSES - определяет максимальное число процессов операционной системы, которые могут присоединяться к Oracle, включая все фоновые процессы. Описание параметра на metalink

Параметр TRANSACTIONS_PER_ROLLBACK_SEGMENT по умолчанию равен 5. Для Oracle 8i.

Параметр MAX_ROLLBACK_SEGMENTS должен быть >= (кол-во rollback segment'ов+ 1) иначе Oracle при попытке открыть базу выдаст ошибку:

ORA-01599: failed to acquire rollback segment (2), cache space is full (currently has (1) entries)

Рекомендации Tom Kyte по размещению rollback segment и использованию optimal для 9i на английском и ее перевод

Q:  Что значит snaphot too old (ORA-01555) и как с этим бороться  ?

A:  Обычно это значит что информация необходимая для вашего запроса была переписана в rollback segment'. 

Во время вашей транзакции (запроса) фиксируется время ее начала (вернее SCN). В это время другая транзакция может менять те же данные которые вы хотите получить. Чтобы воссоздать для Вас состояние данных которые было при старте транзакции используются rollback segment. Но транзакция изменяющая данные может закончиться и Oracle на ее место в rollback segment поместит следующую, затерев таким образом важную для вас информацию. Так и возникает ошибка snapshot too old. 

Что делать ?

Можно увеличить кол-во и размеры rollback segments, а можно логические не допускать возникновения такой ситуации. 

Q:  Как перевести БД в archivelog режим  ?

A:  Нужно остановить инстанс - поправить init.ora:

log_archive_start = true

#log destination

log_archive_dest_1 = "location=/jet/oracle/admin/DVP/arch" 

log_archive_min_succeed_dest = 1

#

#or log_archive_dest="log_archive_dest"

 

log_archive_format  = arch%s.arc   # %s show sequence number %t - thread number

Стартовать инстанс следующим образом:

SVRMGRL> startup mount

SVRMGRL> alter database archivelog;

SVRMGRL> alter database open;

Выполнить архивацию 

SVRMGRL> archive log all;

проверить что в директории log_archive_dest_1 появляются файлы

Другие полезные команды:

SQL>alter system set log_archive_dest = '/jet/oracle/arch';

SQL> alter system archive log start (stop);

SQL> archive log list;

 

Чтобы вывести БД из режима archivelog нужно:

Нужно остановить инстанс - поправить init.ora:

log_archive_start = false

Стартовать инстанс следующим образом:

SVRMGRL> startup mount

SVRMGRL> alter database noarchivelog;

SVRMGRL> alter database open;

 

Проверить состояние archivelog:

SVRMGR> archive log list

Database log mode No Archive Mode

Automatic archival Disabled

Archive destination ?/dbs/arch

Oldest online log sequence 481

Current log sequence 483

 

Q:  Что скрывают redo логи  ?

A: Я внес изменения в эту статью 21.02.2003.   

Известно, что излишняя генерация redo информации не только замедляет работу системы, но и иногда делает затруднительной ее обслуживание. Мне приходилось видеть системы где кол-во redo измерялось десятками Gb в день.  Это значит, что эти гигабайты должны записаться к Вам на диск, где должно хватить место для них. Также известно, что ваше приложение получит ответ от БД только после того, как будет завершена запись в  redo. Что такое излишняя генерация redo ? - мне кажется, что бывают ситуации, когда явно можно избежать генерации информации, скажем производя большие временные операции в режиме nologging.  Следует проверить не делаются ли такие операции как  create table as select  для временных операций, загрузки данных с последующей промежуточной обработкой и переносом в основные данные. И постараться, по возможности, делать их в режиме nologging. 

Давайте разберемся, что же содержат redo, точнее сколько данных попадает в redo файлы.

В документации,  в разделе Online Redo Log Contents написано:
"
For example, if you change a salary value in an employee table, you generate a redo record containing change vectors that describe changes to the data segment block for the table, the rollback segment data block, and the transaction table of the rollback segments
"
Не очень понятно, так сколько же redo я произвожу ? Что происходит если я делаю update маленького поля большой записи ? Давайте сделаем тест. Завидим таблицу с большим полем и маленьким и выполним с ними insert и update.

SQL> create table redo_test (is_up varchar2(1) default 'N', data varchar2 (2000));

Table created.

SQL> set autotrace on;

SQL> insert into redo_test values ('N', rpad('x', 2000,'x'));

Statistics
----------------------------------------------------------
2 recursive calls
8 db block gets
3 consistent gets
1 physical reads
2668 redo size                       <---------------
848 bytes sent via SQL*Net to client
581 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> update redo_test set is_up = 'Y';

Statistics
----------------------------------------------------------
0 recursive calls
5 db block gets
1 consistent gets
0 physical reads
244 redo size                             <------------------- 
852 bytes sent via SQL*Net to client
558 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed

Во время insert мы получили 2668 байт redo. Что как раз составляет наш объем(~2000 байт) + служебные данные. Во время update - мы получили 244 байта redo - почти все ушло на служебную информацию. Как на нее может уходить по 200 байт - для меня загадка :(((.  

Откуда видно, что в redо пишется только информация измененная в транзакции, необходимая для восстановления БД в случае краха. Таким образом, в  redo хранятся не блоки данных, и не записи целиком,  а именно данные, необходимые для восстановления информации. 

Нужно учитывать что,   redo логи генерятся независимо от того, был ли сделан commit или нет.

Вопрос что содержат rollback segment, описанный ранее в этом разделе неверно, вынесен в отдельный вопрос.

Если вам неудобно пользоваться sqlplus, то вы можете без него узнать сколько вы создали redo с помощью вот такого запроса. Этот запроса показывает объем redo с момента старта сессии. 

11.03.2002 г. Оказалось что не я один такой любопытный :)). Хорошая статья о redo, их тюнинге, log_miner c сайта http://www.dba-village.com. Там же приводятся сравнительные таблицы о кол-ве генерации redo в различных случаях.

Q:  Что содержатся в Rollback segment'ах  ? [Уровень -для начинающих] (обновлено 03.06.2003)

A:  Ниже я пытаюсь разобраться сколько информации и какая информация пишется в момент DML операций и как происходит воссоздание read consistent view. 

Самые общие слова : rbs содержат образы  информации до старта нашей транзакции и эти образы  используются для read consistency, восстановления БД, и в случае отката транзакции.  Есть следующие мнения  на этот счет:

  • A rollback entry consists of pre-update image value, block address, and data file number, transaction ID and status of the transaction (Active or Committed), this is a single rollback entry. Сама  статья здесь

  • Information in a rollback segment consists of several rollback entries. Among other information, a rollback entry includes block information. (the file number and block ID corresponding to the data that was changed) and the data as it existed before an operation in a transaction. Oracle links rollback entries for the same transaction, so the entries can be found easily if necessary for transaction rollback. Oracle9i Database Concepts Release 2 (9.2)

Но больше всего мне понравились материалы  с сервера  http://www.optimaldba.com/ собственно  две статьи: Rollback Segment and UNDO Internals и Rollback Segment and Undo Internals обе принадлежащие Daniel W. Fink (это локальные их копии)

В этих статьях он приводит dump блоков данных и блоков rollback segments (!?), из которых видно, что, при update 1 поля наряду с адресной информацией (file id, extent id, block id) содержаться номер поля и старые значения.  Повторить этот эксперимент не просто, так что лучше прочитать оригинал. Я же попробую привести примерный перевод параграфа, как происходит создание read consistent view.

  1. Читается блок данных

  2. Читается заголовок записи.

  3. Проверяется LockByte, существуют ли ITL(interest transaction list)  записи.

  4. Из ITL листа, который храниться в заголовке каждого блока извлекаются ID транзакций.

  5. Читается Transaction Table. Если транзакция была завершена (commit) и имеет SCN (system change number) меньше чем SCN запроса блок очищается (?) и читается следующий блок.

  6. Читается последний отмеченный undo block. 

  7. Если id транзакции не совпадает с id транзакции в этом блоке, то мы полагаем что интересный нам undo block был переписан и сигналим ORA-1650, Snapshot too old

  8. Если id транзакции одинаковы начинаем реконструировать блок данных в памяти (у нас есть номера полей и их значения).

  9. Так как изменения могут быть более чем в одном undo блоке, то находим их все. 

См. также статью metalink с подробностями о  rollback segment'ах. 

Q:  ARCH: Archival stopped (ORA-16020) ?

A:  Из-за проблем с оборудованием, или когда закончилось место на диске,  Oracle может остановить .автоматическое архивирование, если какое-то кол-во попыток выполнить архивацию  не увенчались успехом.   

Если мы уже исправили ситуацию, то для продолжения автоматической архивации: 

alter system set LOG_ARCHIVE_DEST_STATE_1 = enable и затем 

alter system set LOG_ARCHIVE_DEST_1 = 'location=/archivelogpath reopen'

Q:  Как посмотреть открытые курсоры (ORA-001000) ?

A:  Все о курсорах, какие они бывают, и параметрах сервера связанных с курсорами я написал здесь.

Q:  Как освободить PGA memory при  Dedicated режиме (FREE_UNUSED_USER_MEMORY) ?

A:  Оригинальная идея принадлежит Tom Kyte.  Далее показывается что dbms_session.free_unsed_user_memory не эффективна при использовании DEDICATED. 

Я производил свои эксперименты на Sun платформе. 

bash-2.03$ uname -a 
SunOS smap4.service.jet.msk.su 5.8 Generic_108528-17 sun4u sparc SUNW,Sun-Fire-280R

SQL> @mystat pga

NAME VALUE
---------------------------------------------------------------- ----------
session pga memory 119360
session pga memory max 119360

Узнаем pid процесса 

select a.spid
from v$process a, v$session b
where a.addr = b.paddr and b.audsid = userenv ('sessionid')
/
SPID
---------
4623

Посмотрим сколько он занимает памяти в ОС

!pmap -x 4623

FF370000 8 8 8 - read/exec libskgxp8.so
FF380000 8 8 - 8 read/write/exec libskgxp8.so
FF390000 8 8 8 - read/exec libdl.so.1
FF3A0000 8 8 - 8 read/write/exec [ anon ]
FF3B0000 152 152 152 - read/exec ld.so.1
FF3E6000 8 8 - 8 read/write/exec ld.so.1
FFBE6000 40 40 - 40 read/write/exec [ stack ]
-------- ------ ------ ------ ------
total Kb 601856 586744 586008 736

Нас интересует последнее число (колонка Private) - 736Kb

SQL> @mystat pga

NAME VALUE
---------------------------------------------------------------- ----------
session pga memory 127664
session pga memory max 127664

Выполним запрос 

SQL> select * from all_objects order by 1;

.......

23481 rows selected.

Снова повторим:

!pmap -x 4623

FFBE4000 48 48 - 48 read/write/exec [ stack ]
-------- ------ ------ ------ ------
total Kb 601904 586800 586016 784

SQL> @mystat pga

NAME VALUE
---------------------------------------------------------------- ----------
session pga memory 170528
session pga memory max 170528

Обратим внимание что 170528 - 127664 = 42594 (PGA), а 784 - 736 = 48Kb.  Видно расхождение, примерно в 5 Кб. Объяснить я его не могу. Но по порядку величины показания сходятся.  Теперь самое интересное. Освободим память.

SQL> exec dbms_session.FREE_UNUSED_USER_MEMORY;

SQL> @mystat pga

NAME VALUE
---------------------------------------------------------------- ----------
session pga memory 127664
session pga memory max 223468

Т.е. PGA вернулась к своему начальному значению. А что покажет pmem ? 

FFBE4000 48 48 - 48 read/write/exec [ stack ]
-------- ------ ------ ------ ------
total Kb 601960 586840 586016 824

Только увеличение значения (824). Это связано с вызовом dbms_session.  Так что эта процедура не освобождает память в ОС.

Q: Что делать  с RMAN-06089: XXX not found ?

A:  Обычная ситуация когда это возникает,  это случай, когда  требуемый при архивации лог был удален с диска. Проверьте, нет ли какого-нибудь внешнего процесса, который удаляет логи.  Но мне также удалось встретиться с ситуацией, когда такая ошибка происходит, как результат тестового восстановления БД на другом сервере (standby). Backup на primary сервере стал это выдавать. Помогла только команда проверки (crosscheck) archive log ов.  Видимо, во время восстановления, логи помечаются как восстановленные и они требуются при слудующем backup (???). Данное поведение отмечено на 8.1.7, Sun Solaris.

Q:  Что делать с сообщением ARCH: Failed to archive log ?

A:  Выглядит это визуально так: сначала arch не пишет что не может архивировать лог, чуть позже это ему удается. Проявляется (у меня) при достаточной загруженности дисковой подсистемы. Наверно, неудачно выбраны расположения redo log и archive_log_dest. Но, также можно попробовать увеличить параметр _log_archive_buffer_size отвечающий за оптимизацию процедуры копирования. У меня он оказался равен 64. Думаю что значение 1024 должно исправить ситуацию. Все hidden параметры можно посмотреть с помощью следующего скрипта. 

Более грамотно с большими подробностями о принципах работы ARCH можно прочитать у Стива Адамса

Q: У меня маленький controlfile (kccrsz: denied expansion of controlfile в alert.log) ?

A: Вот такие сообщения  могут появляться в alert.log:

Thread 1 advanced to log sequence 69156

Current log# 3 seq# 69156 mem# 0: /oracle/oradata/SMAP/redo03.log

kccrsz: denied expansion of controlfile section 9 by 661 record(s)

the number of records is already at maximum value (65535)

При создании controlfile несколько параметров являются определяющими для его размера: MAXDATAFILES, MAXLOGFILES, MAXLOGMEMBERS, MAXLOGHISTORY, and MAXINSTANCES (см документацию)

Эти размеры являются статическим и изменить их можно только пересозданием controlfile. В тоже время, параметр CONTROL_FILE_RECORD_KEEP_TIME (установленный по умолчанию в 7 ) указывает сколько времени в днях следует хранить информацию для восстановления ( в том числе список archivelogs). Если у Вас накапливается больше логов чем указано в параметре maxloghistory за кол-во дней  меньшее чем control_file_record_keep_time то и происходит эта ошибка. 

Как workaround, если не используется backup  с помощью rman можно установить параметр CONTROL_FILE_RECORD_KEEP_TIME = 0 в init.ora. Иначе рекомендуется пересоздавать controlfile.

Оригинальная статья металинк.

Стив Адамс о структуре control file.

Q: Что дает мне установка параметров timed_statistics и timed_os_statistics ?

A:  По умолчанию, оба этих параметра выключены. При их включении, oracle начинает дополнительно собирать времена выполнения и ожиданий используя системные вызовы. 

timed_os_statistics(sec)  - интервал в секундах, в течении которого Oracle собирает статистику с начала запроса и(или) до завершения запроса (документация, metalink note)

timed_statistics (true|false) - указывает собирает ли Oracle времена выполнения или нет. С точки зрения пользователя эти времена будут присутствовать например в v$sysstat и trc файлах (документация, metalink note). 

Steve Adams утверждает что на Solaris timed_statistics использует системный вызов times(), а timed_os_statistics использует вызов prstat(). 

Устанавливать эти параметры для production системы рекомендуется только с помощью alter system, а не в init.ora. Поскольку сбор статистики занимает дополнительные ресурсы. Я и следую этой рекомендации.

alter system set timed_statistics = true

alter system set timed_os_statistics = 10

Вот что происходит в версии 8.1.7 после включения timed_os_statistics. Начинают заполняться статистки 

SQL> select name, value from v$sysstat where upper(name) like '%CPU%';

NAME VALUE
---------------------------------------------------------------- ----------
recursive cpu usage 3
CPU used when call started 74
CPU used by this session 74
parse time cpu 51
OS User level CPU time 136
OS System call CPU time 161
OS Other system trap CPU time 0
OS Wait-cpu (latency) time 2

 

Но что совсем не понятно, на HP и WIndows этого не происходит !?. 

Описание какие статистики из v$sysstat бывают и что они значат.

Q:  Как все-таки проанализировать схему (analyze schema) ? (обновлен 28.08.2004, для начинающих)

A:  Существуют следующие  возможности: 

  • использовать analyze table (index) для всех своих объектов. Этот способ я реализовал например в процедуре  analyze_schema пакета dba_utils

  • использовать dbms_utility.analyze_schema 

  • использовать dbms_stats (документация8i, документация 9i ) 

Какой из способов использовать более религиозный вопрос и(или) специального использования. Я использую dbms_stats как в целом и рекомендует Oracle.

Вот пример вызова:

begin
dbms_stats.gather_schema_stats (

ownname =>'SMAP',    -- Владелец схемы

 

estimate_percent=> 90, -- Оценить 90 процентов записей 

                       --и, возможно 

block_sample => TRUE,   -- Выбрать блок для анализа случайным образом 

 

method_opt => 'for all indexed columns',

cascade => TRUE     -- Собрать статистику для так же и для индексов

);
end;
/

В принципе следует использовать либо estimate_percent либо block_sample. Использование block_sample гораздо дешевле, но и сбор статистки может получиться неаккуратным. В документации также написано, что для сбора статистки по индексам block_sample не используется.

Оказывается, если часть таблиц в схеме недоступна (например находятся offline) то вышеописанная процедура (8.1.7) возвращает ошибку. Тогда я переписал ее так:

declare 
e_tablespace_offline exception;
PRAGMA EXCEPTION_INIT (e_tablespace_offline , -376);
begin

for c_rec in (select table_name from user_tables where temporary <> 'Y' ) loop 
begin 
dbms_stats.gather_table_stats (ownname =>'SMAP', tabname => c_rec.table_name, 
estimate_percent=> 20, block_sample => TRUE, method_opt => 'for all indexed columns',
cascade => TRUE);

exception when e_tablespace_offline then 
null;
end;

end loop;

end;
/

 

И наконец, один из примеров почему нужно использовать dbms_stats, а не analyze - параллельное выполнение 

begin
dbms_stats.gather_schema_stats (
ownname =>'OD', -- 
estimate_percent => 20,    -- dbms_stats.auto_sample_size in 9i
method_opt => 'for all indexed columns size 1',    -- size auto in  9i                                        degree => 8,          -- степень параллельности 
cascade => TRUE 
);

 

Очень сильное впечатление о возможностях автоматического сбора статистики оставляет Note:237901.1

Загадочное слово SIZE 1 обозначает" maximum number of buckets for the histogram". См.  Note:1031826.6

Очень короткая выдержка оттуда, для понимания, нужно ли размышлять над SIZE  

When to Not Use Histograms:

o all predicates on the column use bind variables

o the column data is uniformly distributed

o the column is not used in WHERE clauses of queries

o the column is unique and is used only with equality predicates

Q:  Как выполнить rotate alert.log (listener.ora) файла ? (обновлен 15.12.2003)

A:  Действительно, со временем размер alert.log может стать существенным и очень неудобным для работы. К счастью, известно, что Oracle перед выполнением записи в alert.log вновь открывает его. Таким образом, если просто переименовать alert.log в скажем alert.log.old, то при первой же попытке записать в alert.log он вновь будет создан. Все вышеперечисленное справедливо для Unix.

На сайте oracledba.co.uk есть пример скрипта на shell, который выполняет rotate, оставляя в alert.log указанное кол-во строк, а вслучае нахождения в alert.log ошибок посылает его по почте. Сам скрипт здесь. Мне кажется бессмысленным проверять alert.log только в момент rotate, поскольку надо делать это гораздо чаще. Возможно хорошая идея - разбить этот скрипт на 2. 

Для listener.ora нужно остановить протоколирование работы, затем выполнить rotate, после чего вновь возобновить протоколирование

lsnrctl set log_status off

<rotate here>

lsnrctl set log_status on

Q:  Как уменьшить файл данных ?

A:  Иногда, после временных или промежуточных операций файл данных становиться большим, и не хватает место в ОС под другие данные. Естественно возникает идея уменьшить его.

alter database datafile '/oracle/oradata/DVP/smappl.dbf' resize 20M
*
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value

Оказывается, низзя :)). Но dba_free_space показывает что места в этом файле очень много ? Дело тут вот в чем. Если объект занял старшие блоки в файле, даже если в младших уже давно ничего нет, уменьшить файл не получиться. Единственная надежда, узнать что за объект находить "вверху" файла, переместить его, попробовать уменьшить файл вновь.  Скрипт last_hero.sql показывает этот, последний, героический объект. 

Q:  Как rman ухитряется копировать файлы без alter tablespace begin backup  ?

A:  Меня также всегда интересовал вопрос: что же такого дополнительного пишется в redo во время begin backup ? Ниже ответ.

Мы понимаем, что если скопировать файл данных средствами ОС, но блоки в этот момент могут изменяться DBWR, и таким образом есть возможность скопировать не консистентный блок  (fractured block) 

Когда Вы выполняете backup без rman вы должны поместить tablespace в backup моду и далее скопировать данные с помощью средств ОС. Когда табличное пространство не находиться в backup моде, Oracle записывает в redo файлы только изменения, а не весь блок (см. что скрывают redo логи).  Когда табличное пространтсво в backup моде Oracle записывает before-image  каждого измененного блока табличного пространства в redo лог, перед его изменением. Затем Oracle отдельно записывает изменения в redo лог.   Когда Вы выполняете восстановление, Oracle применяет блоки и изменения к ним, таким образом не важно что во время копирования средствами ОС блок мог быть не консистентным (fractured).

А что же RMAN ?

Во время backup c помошью rman Oracle сам выполняет чтение файлов данных. Читается полностью блок данных, и определяется консистентен ли блок сравнивая заголовок и хвост каждого блока. Если получается что блок не консистентен, блок перечитывается, пока ситуация не исправиться. Таким образом нет необходимости переводить табличное пространство в  begin backup.

Вывод такой: даже c rman нужно проводить backup только когда число изменений в вашей системе минимально.

Найдено в документации 

Q:   Как закачать в standby пропущенные логи  ?

A:  Эта ситуация называется правильным термином log gap. Это когда по какой-то причине primary DB не передала лог на recover managed standby. Оказывается, что даже если передать лог вручную - standby не принимает его. 

Если в этот момент посмотреть в v$archived_log на standby то там нет этого пропущенного лог файла. Т.е. standby о нем не знает. 

В этой ситуации metalink рекомендуется перейти в ручной способ поддержки standby закачать то что передано вручную потом снова вернуться в автоматический режим.

Есть еще совет - сделать standby destination mandotory. Тогда не будет пропущенных логов. Но будет вставать основная БД в случае если не сможет отправить логи на standby.

Оригинальная статья metalink.

Q:  Что делать с ORA -01578 Block Corruption?

A: Каждый  форматированный блок данных Oracle имеет размер DB_BLOCK_SIZE и определенную структуру данных. Неформатированный блок должен иметь нулевую длину.  Блок имеет 2 заголовка - в начале (header) и конце блока (footer). Заголовки  блока содержит служебную информацию.  В то время, как блок считывается в буферный кэш, производится его анализ. Этот анализ включает в себя проверку, что считан именно требуемый блок, а также проверку информации в обоих заголовках, чтобы убедиться что блок считан полностью. Если эта проверка не прошла, тогда  и возникает ошибка: 

ORA-01578: ORACLE data block corrupted

(file # %s, block # %s)

Если включен параметр db_block_checksum то дополнительно производится проверка контрольной суммы блока. 

Читать подробнее описание этого процесса на  metalink. Но не расстраивайтесь раньше времени !. Эта  ошибка еще не говорит о том, что блок физически поврежден. Причин может несколько.  Как определить какой объект пострадал и что делать дальше: объемная статья metalink.

Если пострадала таблица, то есть вариант спасти часть данных, или установив параметр сессии или указав конкретную таблицу:

ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10';

execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('<schema>','<tablename>'.'<partition>');

Читать также, из чего состоит блок данных, как рассчитать размер заголовка блока данных через v$type_size.

Q:  Как правильно выбрать параметры хранения СLOB'ов ?

A:  Одними из основных параметров являются 

  • метод хранения clob (enable/disable storage in row) 

  • размер единицы хранения (chunk) 

  • размер сегмента отката (pctversion)

Enable/Disable storage in row

Если Вы разрешаете хранить lob в таблице, то там реально храниться только первые 4000 (3964) байт lob'а. Если lob превышает эти размеры,  то данные сверх 4000 байт хранится отдельно. UNDO информация записывается только для этих первых 4000 байт (или реального размера LOB если он меньше)

Если Вы запрещаете хранить lob вместе с таблицей, то в таблице хранятся только 20 байтный LOB LOCATOR, который содержит ссылку на LOB INDEX. UNDO информация записывается только для изменений LOB LOCATOR и LOB INDEX.

Chunk

Единица хранения LOB и указывается в момент  создания таблицы. Размер chunk округляется до кратного параметру db_block_size.Если размер LOB меньше чем chunk то, все рано, занимается chunk полностью. Посмотрим на пример (db_block_size = 8192):

create table test_clob (c2 clob) lob(c2) store as my_lob (DISABLE STORAGE IN ROW storage (initial 100K NEXT 100K) chunk 32K);

sys@DVP8.1.7> insert into test_clob values ('x');

1 row created.

sys@DVP8.1.7> insert into test_clob values ('x');

1 row created.

sys@DVP8.1.7> commit;

sys@DVP8.1.7> select sum(dbms_lob.getlength(c2)) from test_clob;

  2

select sum(bytes) from user_extents where segment_name = 'MY_LOB';

212992

т.е. на два chunk по 32k потребовалось 2 extent'а по 100k ?  

Но если вставлять записи дальше, видно что они укладываются в эти же 2 extent'а. На мой взгляд это говорит о том, что мы можем учитывать место только с точностью до extent'а. 

analyze table test_clob compute statistics;

sys@DVP8.1.7> exec dba_utils.show_space ('MY_LOB', USER, 'LOB');
Free Blocks :8
Total Blocks :26
Total Bytes :212,992
Unused Blocks :4
Unused Bytes :32,768
Last Used Ext FileId :31
Last Used Ext BlockId:17169
Last Used Block :12

Если используя insert выше, добавлять записи и смотреть после каждой записи show_space, будет видно что Free Blocks дойдет до 0, после чего затребует себе дополнительный extent. Unused Bytes будет почему-то возрастать. Отгадка в следующем параграфе.

pctversion

PCTVERSION определяет процент от общего места, оставляемый под старые версии LOB, для поддержания целостности чтения (read consistency) сессий, который начались до обновления LOB.

Посмотрим чему у нас равен pctversion:

sys@DVP8.1.7> select PCTVERSION from user_lobs where COLUMN_NAME = 'C2';
10

Теперь проведем несложные вычисления и получим что Unused Bytes = 10% от Total Bytes + 1 block.

Redo size 

sys@DVP8.1.7> insert into test_clob values ('xsdsdsdsdsdsds');

1 row created.


Statistics
----------------------------------------------------------
0 recursive calls
11 db block gets
3 consistent gets
0 physical reads
33952 redo size
646 bytes sent via SQL*Net to client
569 bytes received via SQL*Net from client
6 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed

 

Видно что размер redo равен chunk + константа. Оказывается также что, не важно сколько вы поместили в LOB - 1 байт или 30 Кб - redo остается таким же. 

Есть два утверждения:

  1. Образ  Lob данных до изменения  храниться прямо в lob сегменте. 

  2. Более не нужные старые образы данных  переписываются. Однако Oracle поддерживает процент = pctversion места свободным для старых образов.

Когда возникает ошибка, связанная с невозможностью восстановить старый образ,  из-за неверно угаданного PCTVERSION звучит она как:

ORA-01555: snapshot too old: rollback segment number with name "" too small 

Обратите внимание, имя rollback segment - пустое. 

Заключение

С некоторыми натяжками можно сказать так: для хранения LOB используются не блоки, а chunk, выделить меньше под запись чем chunk нельзя. В остальном они очень похожи на обычные segment'ы. Поэтому определяющими  параметрами для оптимизации места являются CHUNK и верное значение PCTVERSION. 

Описание основных параметров для LOB'ов  и как работать с LOB'ами на metalink.

Q: Как заcтавить работать listener c двумя или более сетевыми интерфейсами  ?         (создан  16.05.2003 благодаря помощи коллег)

A:  На Unix в версии 8.1.7 есть очень простое решение:

В строке ADDRESS  в качестве HOST указывается имя машины, совпадающие с тем что написано в /etc/nodename. Тогда Listener сам слушает указанный порт на всех поднятых  сетевых интерфейсах машины. 

Проверить это можно с помощью команды 

netstat -na | grep 1521 

*1521* 

Если требуется обратная задача, т.е. заставить слушать listener на одном интерфейсе, укажите вместо имени хоста конкретный ip-адрес. Тогда в netstat будет на * а указанный IP адрес.

Проще всего первоначальную диагностику проводить с помощью команды telnet <имя хоста> <ip>. Если удалось получить ответ - значит listener принимает запросы.

Одна из статей metalink на эту тему

Q:  Установке контекстного поиска в 9i ?
(обновлен 09.11.2003 by Кирилл Викторов)

A:  Пользователь ctxsys теперь по умолчанию залочен.

SQL> alter user ctxsys account unlock identified by ctxsys;

Ручная инсталляция в 9i практически такая же как и в 8i. (см ниже замечания Кирилла Викторова) 

Чтобы убедиться что у Вас все в порядке сначала протестируйте вызов внешней библиотеки индексера:

SQL> conn ctxsys/ctxsys
Connected.
SQL> exec ctx_adm.test_extproc;
BEGIN ctx_adm.test_extproc; END;

*
ERROR at line 1:
ORA-20000: file not found
DRG-50704: file not found
ORA-28575: unable to open RPC connection to external procedure agent
ORA-06512: at "CTXSYS.DRUE", line 157
ORA-06512: at "CTXSYS.CTX_ADM", line 286
ORA-06512: at line 1

Упс (в 9.0.1, в 9.2 нормально сразу). Если у Вас тоже "упс", тогда надо убедиться в корректной настройке listener'а БД.

Вот что нужно сделать:

listener.ora

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = kakadu)(PORT = 1521))
)
)
)

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /space/oracle/ora92)
(ENVS = LD_LIBRARY_PATH=/space/oracle/ora92/ctx/lib)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = DSV)
(ORACLE_HOME = /space/oracle/ora92)
(SID_NAME = DSV)
)
)

 

tnsnames.ora 

DSV =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = kakadu)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DSV)
)
)

EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)

Перезапустить листенер (lsnrctl stop| start), выполнить проверку: 

tnsping EXTPROC_CONNECTION_DATA

Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO)))
OK (10 msec)

Запустите ctxsrv. Все как в 8i.

ctxsrv -user ctxsys/ctxsys -logfile /tmp/ctxlog.log &

Теперь создадим тестовый примерчик:

SQL> create user dsvolk identified by oracle default tablespace users temporary tablespace temp;

User created.

SQL> grant connect, resource to dsvolk;

Grant succeeded.

SQL> grant ctxapp to dsvolk;

Grant succeeded.

SQL> create table test_context (id number, text clob);

Table created.

SQL> create index test_context_ic on test_context (text) indextype is ctxsys.context;

Index created.

SQL> insert into test_context values (1,'Русское слово');

1 row created.

SQL> commit;

SQL> select text from test_context where contains (text, 'Русское') > 0;

TEXT
--------------------------------------------------------------------------------
Русское слово

Что видно из этого примера ? Общие принципы остались те же. Добавились возможности для разработчика, описанные в New features от metalink

Большой FAQ на metalink'e посвященный Oracle Text.

Замечания Кирилла Викторова

1. Если нет ctx, то нет и tablespace DRSYS.

Пример создания (взят из инсталляционного скрипта имя_инстансаdrsys.sh):

CREATE TABLESPACE DRSYS DATAFILE

'/usr/oracle/products/9.2.0/oradata/grotta/drsys01.dbf' SIZE 84M REUSE

AUTOEXTEND OFF MINIMUM EXTENT 64K

DEFAULT STORAGE ( INITIAL 64K NEXT 64K MINEXTENTS 1 MAXEXTENTS

UNLIMITED PCTINCREASE 50);

Теперь на тему скрипта SMAPcontext.

1.

/space/oracle/bin/sqlplus << EOF

internal

Сам понимаешь, такое работать не будет, нет слова connect

Далее все пишу про 9i

$ORACLE_HOME/bin/sqlplus /nolog << EOF

conn sys/manager as sysdba

@?/ctx/admin/dr0csys ctxsys DRSYS DRSYS

не пройдет из-за

ORA-12911: permanent tablespace cannot be temporary tablespace

нужно @?/ctx/admin/dr0csys ctxsys DRSYS TEMP

Ну и библиотеку от 9i зацепить, а не от 8i

@?/ctx/admin/dr0inst $ORACLE_HOME/ctx/lib/libctxx9.so

 

Q:  Что содержит controlfile  ?

A:  Выдержка из concept guide

  • The database name
  • The timestamp of database creation
  • The names and locations of associated datafiles and online redo log files
  • Tablespace information
  • Datafile offline ranges
  • The log history
  • Archived log information
  • Backup set and backup piece information
  • Backup datafile and redo log information
  • Datafile copy information
  • The current log sequence number
  • Checkpoint information

См. concept guide 

Но можно посмотреть и самому:

select type from V$CONTROLFILE_RECORD_SECTION
SQL> /
DATABASE
CKPT PROGRESS
REDO THREAD
REDO LOG
DATAFILE
FILENAME
TABLESPACE
TEMPORARY FILENAME
RMAN CONFIGURATION
LOG HISTORY
OFFLINE RANGE
ARCHIVED LOG
BACKUP SET
BACKUP PIECE
BACKUP DATAFILE
BACKUP REDOLOG
DATAFILE COPY
BACKUP CORRUPTION
COPY CORRUPTION
DELETED OBJECT
PROXY COPY
RESERVED4

 

Controlfile содержит как минимум секции двух типов. Одни из них могут использоваться в циклической манере, т.е. перезаписываться, другие нет. 

На размер controlfile влияют параметры создания БД (такие как MAXLOGFILES, MAXDATAFILES и т.п.)

Параметр CONTROL_FILE_RECORD_KEEP_TIME похоже, влияет только на время хранения истории backup'ов, и позволяет хранить до 65535 архивных логов. Т.е. больше не получиться. Хотя, в этом вопросе я не уверен, если кто-то имеет больше информации - сообщите мне.

Стив Адамс о структуре control file.

См. также faq:  у меня маленький controlfile

Q:  Как посмотреть shared memory segment занятые oracle на Unix ? (создан  16.05.2003 благодаря рассылке dba-villlage.com)

A:  На Solaris есть известный администраторам способ:

ipcs -ms
IPC status from  as of ðÎ 02 éÀÎ 2003 10:41:24
T         ID      KEY        MODE        OWNER    GROUP
Shared Memory:
m          0   0x50008c57 --rw-r--r--     root     root
m        101   0xcd5854e8 --rw-r-----   oracle      dba
Semaphores:
s     196608   0x3d887bfc --ra-r-----   oracle      dba
s          1   0x100ddc3  --ra-ra-ra-     root    other
Но самое занятное, что подобная утилита есть в составе Oracle. $ORACLE_HOME/bin/sysrevs
bash-2.03$ ./sysresv 

IPC Resources for ORACLE_SID "ORCL6" :
Shared Memory:
ID              KEY
101             0xcd5854e8
Semaphores:
ID              KEY
196608          0x3d887bfc
Oracle Instance alive for sid "ORCL6"
В принципе можно использовать этот факт для проверки, поднят ли инстанс. Правда это вовсе не говорит о том, что БД доступна.
Q:  Как резервировать и восстанавливать (backup/recovery) временные табличные пространства ? (создан 23.06.2003, для начинающих, версия 9i)

A:  Вообще говоря, временные табличные пространства не содержат данных, и поэтому, если вы потеряли его, Вы всегда можете его пересоздать сами. 

Если Вы создавали свое временное табличное пространство при помощи синтаксиса: 

CREATE TEMPORARY TABLESPACE .. TEMPFILE

create temporary tablespace temp2 tempfile '/tmp/tmp.dbf' size 10M extent management local;

То оно не входит в не входит в backup, если используется Rman. Но даже при отсутствии на диске tempfile'ов БД стартует нормально, благодаря тому, что Oracle не пишет checkpoint информацию в temporary файлы. При этом в alert log пишется ошибка вида: 

Errors in file /space/oracle/ora92/admin/DSV/bdump/dsv_dbw0_19437.trc:
ORA-01186: file 202 failed verification tests
ORA-01157: cannot identify/lock data file 202 - see DBWR trace file
ORA-01110: data file 202: '/tmp/tmp.dbf'
Mon Jun 23 17:54:02 2003
File 202 not verified due to error ORA-01157

Что остается - пересоздавать вручную. Текст можно получить как результат команды 

alter database backup controlfile to trace

В результате в trace файле после create controlfile появилась строчка

ALTER TABLESPACE TEMP2 ADD TEMPFILE '/tmp/tmp.dbf' REUSE;

Вот что я делал. Удалил из OS tempfile (rm). Перестартовал инстанс. Увидел ошибку в alert.log, как и написано выше. Удалил tempfile c помощью 

alter database tempfile '/tmp/tmp.dbf' drop including datafiles;

Потом добавил 

ALTER TABLESPACE TEMP2 ADD TEMPFILE '/tmp/tmp.dbf' size 10M;

Говорят, что уже открыт запрос, на то, чтобы rman сам умел создавать tempfile. Наверно, это действительно случиться. 

См. также metalink Note: 178992.1

Документация о temporary файлах: 

Хорошая Note:160426.1 объясняет разницу в поведении между синтаксисами temporary tablespace и tablespace temporary.

Q:  Я создал временное табличное пространство а места на диске не стало меньше  ? 
(создан 26.06.2003, для начинающих, 8i и 9i,  Unix platforms)

A:  Действительно, если вы создали временное табличное пространство с временными файлом (tempfile), то df -k не отображает, что стало меньше места. С другой стороны ls -l показывает реальный размер файла. Более того, можно создать tempfile размером больше чем, свободное место в файловой системе !

Оказывается, для реализации tempfile на платформах Unix Oracle использовал так называемые sparse файлы. Неиспользованные блоки таких файлов просто не аллокируются в файловой системе, пока они не требуются приложению. 

df показывает кол-во свободных блоков файловой системы, без учета наличия в ней sparse файлов. ls -l - реальный размер файла. Поэтому они и показывают такие разные результаты. 

Какая опасность таится в такой реализации ? Та, что в процессе работы систем файловая система окажется занятой и не хватит места под расширение temp файла.

Выход тоже понятен.  Нужно заполнить временный файл. Либо с помощью большой сортировки, либо с помощью, скажем dd . См. например демострацию Tom Kyte

 Еще о sparse файлах http://www.houseofbrick.com/docs/Bricks_2002-06.pdf

На metalink написано, что в документации на 8i про такое поведение просто забыли написать, но в 9i вроде все поправлено. 

Q:  Как восстановить БД с использованием rman но без использования каталога ?
(создан 13.08.2003, обновлен 29.08.2003 для начинающих, 8i и 9i, при участии Александра Лампа)

A:  Оказывается (и это документировано), что если Вы восстанавливает БД 8.1.7 с помощью rman без использования каталога, то делать это можно только когда БД смонтирована. А раз так, то нужен controlfile. Да и еще такой, в котором записаны Ваши последние выполненный резервные копирования. Т.е. Вам необходимо выполнять резервное копирования controlfile отдельно от копирования БД (это вообще говоря не вполне верно, см ниже ссылку на Александра Лампа). 

Я использовал команду alter database backup controlfile to 'file_name', некоторые рекомендуют просто брать snapshot controlfile, появляющийся в результате резервного копирования. Согласно документации имя его зависит от платформы. На Solaris 8, 8.1.7 его имя snapcf_<SID>.f
Найти его можно в директории $ORACLE_HOME/dbs или установить его имя с помощью команды set snapshot controlfile name to '<filename'.  

Итак, у Вас есть controlfile. Монтируем БД, восстанавливаем настоящий controfile. После это перезапускаем БД, используя этот восстановленный controlfile. Далее восстанавливаем  файлы данных. 

Даже это не все плохие новости. Оказывается тот controlfile который создается в одном блоке с backup database не содержит записей о том резервном копировании в котоое он сам включен. Требуется выполнять отдельное резервное копирование controlfile'а. Т.е. последовательность команд примерно такая:

 

run { 

allocate channel c1 type 'sbt_tape'; 

backup database;

 }

run {

ALLOCATE CHANNEL ch00 TYPE 'SBT_TAPE';
BACKUP
# recommended format
FORMAT 'cntrl_%s_%p_%t'
CURRENT CONTROLFILE;
RELEASE CHANNEL ch00;

}

В 9i ситуация улучшилась. Специальная команда controlfile autobackup позволяет выполнять резервное копирование controlfile в специальном формате, который распознается rman без монтирования БД. Читать об этом metalink  

Мой протокол восстановления БД без recovery catalog, скрипты. Полезные статьи metalink Procedures/Restrictions for Point-In-Time Recovery without a Recovery Catalog. Metalink утверждает что для того, чтобы извлечь  controlfile из backup с помощью API требуется обратиться в Oracle Support. Некоторые примеры здесь. Но Александр Ламп, показал мне пример скрипта горячего архивирования базы, и фрагмент инструкции восстановления базы из такого backup, с восстановлением controlfile с помощью API. 

Q:  Как включить  Dead Connection Detection (DCD) ?
(создан 18.08.2003, для начинающих, 8i и 9i, Unix, обновлен 26.08.2003, Windows  )

A:  DCD представляет собой серверный механизм (вернее возможность протокола sqlnet 2.2 и net*8), который через указанное время посылает пробный пакет клиенту, пытаясь определить его работоспособность. Казалось бы просто, в соответствии с документацией указать в файле sqlnet.ora на сервере СУБД параметр 

SQLNET.EXPIRE_TIME= <кол-во минут>

При этом sqlnet.ora file должен быть в директори указанной параметром  $TNS_ADMIN или $ORACLE_HOME/network/admin

Но ! А как же убедиться что это работает ? Вот тут и начинаются приколы. Рекомендуется установить в sqlnet.ora параметр 

trace_level_server=16

И искать в trace файлах ($ORACLE_HOME/network/trace/svr_<PID>) заветные слова: 

niotns: Not enabling dead connection detection.

Это пока все отключено. Установливаем sqlnet.expire_time и смотрим :

nstimini: entry
nstimig: entry
nstimig: normal exit
nstimini: initializing NLTM in asynchronous mode
nstimini: normal exit
nstimstart: entry

Замечу, что если мы выполняем connect локально, по IPC, то и возможность DCD  отключена сразу:

niotns: Dead connection detection being turned off.

Установка вышеуказанных параметров в sqlnet.ora не требует перегрузки БД или listenera (в 9i по крайне мере).

Dead Connection Detection (DCD) Explained и How to Check if Dead Connection Detection (DCD) is Enabled

Вы конечно будете смеяться но на платформе Windows DCD в 8i работает только для первых 16 сессий. Выглядит это в trace файле так:

nstimset: entry nstimset: couldn't rearm timer 

nstimset: can no longer detect dead connections! 

nstimset: error exit 

nstimstart: unable to arm timer for the first time

Обойти это можно установив TCP KeepAlive в HKEY_LOCAL_MACHINE: SYSTEM: CurrentControlSet: Services: Tcpip: Добавить КeepAliveTime : REG_DWORD время в милисекундах. Сохранить, перегрузиться.  Или использовать MTS с числом диспетчеров не более 16. 

В 9i обещано исправление этой несуразицы.

Про KeepALiveTime в google, или на metalink

Q:  Где и в каком порядке ищутся файлы сетевой конфигурации клиента sqlnet.ora и tnsnames.ora
(создан 19.08.2003, для начинающих, 8i и 9i, Sun Solaris )

Для tnsnames.ora порядок поиска следующий:

$ORACLE_HOME/.tnsnames.ora

$TNS_ADMIN/tnsnames.ora

/var/opt/oracle/tnsnames.ora

$ORACLE_HOME/network/admin/tnsnames.ora

Насколько я понял из нескольких произведенных экспериментов, именно в этом порядке они и используются.  Причем используется только первый найденный файл.

Для sqlnet.ora порядок поиска следующий:

$TNS_ADMIN/sqlnet.ora

$ORACLE_HOME/network/admin/sqlnet.ora

$HOME/.sqlnet.ora


Здесь ситуация немного другая. Используются первые два существующие файла из списка. 

Вышеприведенная информация несколько расходится со статьей metalink Which Directories SQL*Net Searches for the Configuration File но была получена с помощью команды truss и я склонен себе доверять :)). 

Q:  MAX_IO_SIZE,  DB_FILE_MULTIBLOCK_READ_COUNT что  это и как это работает  ? (при участии Кирилла Викторова )
(создан 20.08.2003,  9i, Sun Solaris )

A:  MAX_IO_SIZE - видимо (потому что негде это явно не определяется) под этим термином на metalink подразумевается максимальный объем операции ввода вывода (the limitof maximum I/O size per transfer (referred to as max_io_size) NOTE 223117.1)

Далее рассматривается только вариант чтений партиями блоков (db file scattered read).  Oracle выполняет самые операции чтения объемом DB_BLOCK_SIZE x DB_FILE_MULTIBLOCK_READ_COUNT,  но не более чем max_io_size. 

DB_BLOCK_SIZE по умолчанию у меня 8192.

Операционная система и архитектура:

oracle@kakadu:/opt/oracle/ora91/admin/ORCL6/udump>uname -a
SunOS kakadu 5.8 Generic_108528-17 sun4u sparc SUNW,Sun-Fire-280R

 Дальше цитата отсюда Максимальный объем операции ввода- вывода на Solaris определяется переменной maxphys в /etc/system

set maxphys = nnn

по умолчанию равной 131072, а можно и нужно выставить ее в гораздо большее значение - до нескольких мегабайт.

I/O size limit in the Volume Managers (if installed) : 

In case you use Veritas VxVM or Sun DiskSuite, be aware that they also have their internal limit (well, who hasn't any ?) : 

For VxVM : vxio:vol_maxio (value in 512k-blocs, default 512 blocs = 256 Kb) 

For DiskSuite : md:md_paxphys (value bytes, default 131072 bytes= 128 Kb)

Известно что если приложение затребует прочитать массив размером больше чем maxphys, то этот вызов будет разбит на несколько кратных maxphys. 

maxphys - Maximum size of physical I/O requests. If a driver sees a request larger than this size, the driver breaks the request into maxphys size chunks. File systems can and do impose their own limit. Default 126,976 (sun4m and sun4d), 131,072 (sun4u), 57,344 (Intel). The sd driver uses the value of 1,048,576 if the drive supports wide transfers. The ssd driver uses 1,048,576 by default (from Sun.com).

Теперь посмотрим на все это со стороны Oracle. Я предполагал, что при выборе max_io_size учитываются настройки ядра, такие как  maxphys. Но это оказалось не так. Проведем несложный эксперимент описанный у Стива Адамса. Только будем делать full scan не по табличке source$ а по собственной таблице my_source.

SQL>create tablespace ufs_tablespace datafile '/data/ORCL6/ufs_tablespace.dbf' size 1024M extent management local uniform size 10M

SQL> create table my_source storage (initial 100M next 100M ) tablespace ufs_tablespace as select * from sys.source$;
Table created.

SQL>select BLOCK_ID, EXTENT_ID from dba_extents where segment_name = 'MY_SOURCE';

BLOCK_ID EXTENT_ID
---------- ----------
9 0
1289 1
2569 2
3849 3
5129 4
6409 5
7689 6
8969 7
10249 8
11529 9

SQL> select count(*) from my_source;

COUNT(*)
----------
1829640

Будем пробовать full scan при различных установках ядра, задав параметр db_file_multiblock_read_count = 32768 (бесконечно большому числу) и смотреть в trace файл какой же реально порцией произошло чтение. Узнаем текущий maxphys :

echo 'maxphys /D' | adb -k

physmem f7e4
maxphys:
maxphys: 131072

Ага, все по умолчанию. 

Выполняем процедуру Стива Адамса 

затем 

sed -n '/scattered/s/.*p3=//p' orcl6_ora_29694.trc | sort -n | tail -1
64

Т.е. производились чтение по 64 блока 

Переставляем maxphys до значения 1 Mb. Перегружаем машину.

echo 'maxphys /D' | adb -k
physmem 1e747
maxphys:
maxphys: 1048576

Повторяем эксперимент, запуск процедуры Стива Адамса

sed -n '/scattered/s/.*p3=//p' orcl6_ora_29694.trc | sort -n | tail -1
64

Ничего не изменилось ! Т.е. при выборе максимального объема операции ввода выводы max_io_size параметры ядра не участвуют. 

Пробуем raw device. Для экспериментов у меня выделено устройство /dev/rdsk/c1t1d0s1

chown oracle:dba /dev/rdsk/c1t1d0s1

SQL>create tablespace raw_tblsp datafile '/dev/rdsk//c1t1d0s1' size 1000M extent management local uniform size 10M;

SQL>create table my_source storage (initial 100M next 100M ) tablespace raw_tblsp as select * from sys.source$;

Table created.

Запускаем скрипт Стива Адамса, изменив только имя таблицы.

>sed -n '/scattered/s/.*p3=//p' orcl6_ora_4138.trc | sort -n | tail -1
64

Тоже самое. Т.е. размер max_io_size не зависит от типа файла и maxphys.

В принципе, в реальных приложениях редко требуется установливать db_file_multiblock_read_count выше 16. Но, если вашему приложению все-таки требуется производить full scan, то имеет смысл воспользоваться табличными пространствами с нестандартным размером блока на сырых устройствах.

SQL> show parameter db_16

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_16k_cache_size big integer 67108864

SQL> drop tablespace raw_tblsp including CONTENTS and datafiles;

Tablespace dropped.

SQL> create tablespace raw_tblsp datafile '/dev/rdsk//c1t1d0s1' size 1000M blocksize 16k;

Tablespace created.

Далее создаем табличку my_source в табличном пространстве raw_tblsp, выполняем процедуру Стива, получаем 

sed -n '/scattered/s/.*p3=//p' orcl6_ora_7422.trc | sort -n | tail -1
64

Т.е. получить размер max_io_size более 1Mb (64 * 16k блок) в 9i нельзя. На metalink есть упоминания того что oracle вообще не производит чтения размером более 1 mb ни при каких обстоятельствах. По крайне мере на моей машине это так.

Есть интересная деталь. 

Получается что  MAX_IO_SIZE зависит от блока табличного пространства и для платформы Solaris при блоке 8кб равно 512кб.  Для Linux и Windows можно найти здесь.

"db file sequential read" Reference Note. Blocks read using index vs. full table scan by Tom Kyte

mbrc.sql

raw.trc ufs.trc 

Q:  Что делать с ORA-04031 или как рассчитать размер large_pool  для rman? (создан 26.08.2003)
(для начинающих, 8i и 9i)

A: Для каждой операции резервного копирования/восстановления каждая серверная сессия (rman канал) выделяет память под буфера ввода вывода. Эта память выделяется в SGA или PGA серверной сессии, в зависимости от  параметра BACKUP_TAPE_IO_SLAVES. Если он установлен память выделяется в SGA или в large_pool, если последний сконфигурирован. Мне кажется, что если backup_io_slaves = true важно сконфигурировать и рассчитать объем large_pool.

В случае, когда вы используете ленточное устройство, RMAN выделяет два типа буферов - input буфера для чтения с диска и output буфера для записи на ленту. 

Для 9i можно получить представление об их кол-ве и размерах из документации, для 8i из статьи metalink 

Мне также кажется, что определяющим моментом для объема памяти являются параметры  команды backup filesperset и параметр команды configure maxopenfiles. Последний определяет максимальное число входных файлов которые могут быть открыты одновременно.

Так что же все таки делать если Вы получили ORA-04031 ? Поднять large_pool_size или уменьшить вышеперечисленные параметры. 

Q:  Что происходит при импорте данных когда нет требуемого табличного пространства ? (создан 09.10.2003)
(для начинающии , 8i и 9i)

A: Действительно, предположим мы выполнили export пользователя, чьи данные располагались в табличном пространстве  USER_DATA, и пытаемся выполнить  import в другую БД, где нет табличного пространства USER_DATA, а есть лишь табличное пространство USERS. Тогда если создать пользователя, назначить ему табличное пространство USERS по умолчанию, то import настолько умный, что поместит все таблицы в это новое табличное пространство. Есть только неприятное исключение - если таблицы содержат LOB объекты, или это partition  таблицы, то import все-таки закончиться с ошибками 

IMP-00003: ORA-00959 

tablespace <tablespace_name> does not exist

Это описанное в документации поведение:

"If LOB data resides in a tablespace that does not exist at the time of import or the user does not have the necessary quota in that tablespace, the table will not be imported. Because there can be multiple tablespace clauses, including one for the table, Import cannot determine which tablespace clause caused the error."

Единственное средство борьбы это создание indexfile, исправление его, запуск создания проблемных таблиц вручную, затем уже import полностью. 

Q:  Как мониторить длительные процессы ? (v$session_longops)(создан 16.10.2003)
(для начинающих , 8i и 9i)

A: Часто бывает, что запустив длинный запрос, или построение индекса нельзя понять, на какой стадии находиться этот процесс. Но, оказывается что, есть соглашение, по которому разработчики помещают промежуточную информацию во время выполнения таких длительных процедур. Естественно, для некоторых процедур это работает (разработчики выдержали соглашение), для некоторых - нет. Рассмотрим на примере создания таблицы. В текущей сессии (сессия1) узнаем свой SID и SERAIL

SQL> select s.sid
, p.pid
, p.spid
from v$process p
, v$session s
where p.addr = s.paddr
and s.audsid = userenv('sessionid');

SID PID SPID
---------- ---------- ---------
31 40 29353

Далее запустим запрос  

SQL> alter system set timed_statistics = true;

System altered.

SQL> create table test as (select a.* from all_source a, all_source b where rownum < 200000);

 

В параллельной сессии (сессия 2) будет наблюдать за нашим процессом:

SQL> define sid=31
SQL> define serial=17241
SQL> select message from v$session_longops 2 where sid=&sid and serial# = &serial;
from v$session_longopswhere sid=31 and serial# = 17241

 

MESSAGE
--------------------------------------------------------------------------------
Sort/Merge: : 29982 out of 29982 Blocks done
Sort/Merge: : 29982 out of 29982 Blocks done
Sort Output: : 18048 out of 18048 Blocks doneSort Output: : 18048 out of 18048 Blocks done

Если в первой сессии начать строить индекс 

create index test_i on test (name)
/

Во второй можно увидеть 

Table Scan: DSVOLK.TEST: 24081 out of 24081 Blocks done
Sort Output: : 1455 out of 1556 Blocks done

Точный текст сообщений может зависеть от  версии и платформы.

Есть ограничения, при которых информация становиться доступна в v$session_longops:

  • для запросов, таблица должна превышать 10,000 блоков, должен использоваться CBO, и должен быть включен timed_statistcis

  • для прочих операций, операция должны продолжаться не менее 6 секунд. 

Описание  v$session_longops,

Q: Что нам стоит контекстный индекс отстроить ? (создан 16.10.2003)
(для начинающих , 8i и 9i)

A:  Действительно, документация утверждает, что контекстный индекс это вcего лишь 
несколько обычных, реляционных индексов. 

Посмотрим так ли это. Создадим временную таблицу

create table test as (select a.* from all_source a, all_source b where rownum < 200000)
/


Начнем строить по ней индекс 

SQL> create index test_ctx on test (name) indextype is ctxsys.context parameters;

Если это первый в жизни БД (8.1.7) индекс скорее всего ничего не выйдет, с сообщением что не хватает места 
в system tablespace. С глубоким изумлением, обнаружим что у нашего пользователя 
и default_tablespace и temporary_tablespace <> 'SYSTEM' 

Оказывается, что процедуры построения индексов выполняются с правами пользователя drsys, и используют 
temporary_tablespace установленный для него. А по умолчанию это system.

Переставляем 
alter user drsys temporary_tablespace = 'TEMP'

наблюдая за процессом с помощью v$session_longops увидим лишь


Table Scan: DSVOLK.TEST: 24081 out of 24081 Blocks done


Оба-на - никакой сортировки не показывается. Но ведь ясно, что для постоения индекса она нужна ? 


Смотрим v$sort_usage - опять ничего. Но вот ошибочка - 'не могу выделить extent в temp tablespace'.

Что же это такое ?

Наблюдение за v$sql_text показывает наличие объектов
table_1_0_14b_0_0_0 - что есть nested table.

Т.е. судя по всему сортировки данных выполняются в коде pl/sql. 


Таким образом индекс строиться примерно так:

  • заносятся служебные записи в Drsys схему.

  • Создаются pl/sql объекты. При этом используется временное табличное пространтсво пользователя drsys

  • Создается  объект в нужном табличном пространстве  (да, если прервать этот процесс индекс останется !)

  • Начинается постройка индекса.


Остается вопрос - как же понять сколько записей уже индексирована и хватит ли ресурсов для индексации остальных ? 

Добрые разработчики Inermedia дали нам возможность включить logging для context.


connect ctxsys/ctxsys
begin
Ctx_Adm.Set_Parameter
(
param_name => 'log_directory',
param_value => '/var/log/ctxlog.log'
);
end;
/

 

Теперь есть возможность стартовать лог 

Ctx_Output.Start_Log ( logfile => 'idx.log' ); 

Строим индекс 

create index test_ctx on test (name) indextype is ctxsys.context 

 

Останавливаем лог: 

Ctx_Output.End_Log; 

 

Наш лог выглядит примерно так 

20:53:55 10/15/03 begin logging
.........................

17:32:58 10/10/03 377400 documents indexed

17:33:06 10/10/03 Errors reading documents: 0

17:33:06 10/10/03 Index data for 1157 documents to be written to database

17:33:06 10/10/03 memory use: 8306929

17:33:06 10/10/03 Begin sorting the inverted list.

17:33:07 10/10/03 End sorting the inverted list.

17:33:07 10/10/03 Writing index data to database.

17:33:10 10/10/03 index data written to database.

17:33:10 10/10/03 End of document indexing. 377438 documents indexed.

17:33:11 10/10/03 Creating Oracle index "SMAP"."DR$TEXT_PART_I1$X"

18:27:56 10/10/03 log

18:27:56 10/10/03 logging halted



Если в лог ничего не выводиться проверьте настройки переменной 
utl_file_dir. Должна быть 
utl_file_dir = '<log file directory>'

Можно ли как то оптимизировать построение индекса ? У нас есть параметр memory который можно передать таким образом: 

create index <index> on <table>(<field>) indextype is ctxsys.context
parameters('memory 50M'); 

Но в документации, написано не меняйте число по умолчанию (это 50m), эксперименты по уменьшению (до 128k), 
показывают существенное снижение производительности. Установить большее значение также не удается. Так что параметр есть, но пользоваться им практически нельзя. 

Но это еще не все. Есть возможность отстроить индекс мгновенно :)). Конечно при этом уже существующие записи не индексируются, а вот вновь поступающие -  индексируются.

SQL> create index test_ctx on test (name) indextype is ctxsys.context parameters ('nopopulate');

SQL> select token_text from dr$test_ctx$i;
no rows selected

SQL> exec ctx_ddl.sync_index ('TEST_CTX');

PL/SQL procedure successfully completed.

SQL> select token_text from dr$test_ctx$i;

no rows selected

SQL> insert into test (select * from all_source where rownum < 2);

1 row created.

SQL> commit;

Commit complete.

SQL> exec ctx_ddl.sync_index ('TEST_CTX');

PL/SQL procedure successfully completed.

SQL> select token_text from dr$test_ctx$i;

TOKEN_TEXT
----------------------------------------------------------------
CATINDEXMETHODS

 

Data Dictionary cхемы ctxsys

Q:  Что делать с ORA-00020: maximum number of processes (N) exceeded  ? (создан 08.12.2003)
(для начинающих , 8i и 9i)

A:  Само сообщение обозначает, что закончилось число процессов (не сессией пользователей), выделенных БД. В принципе понятно - нужно увеличить значение параметра processes. Но вот беда, нужно закрыть БД, а войти не удается все с тем же сообщением. Я делаю так: опускаю listener. Тогда новые пользователи не могут подсоединиться к БД. Затем я удаляю с помощью kill -9 один из серверных процессов. По истечении некоторого времени (1-2 минуты) мне удается зайти в БД. Естественно не по сети (listener опущен), а по IPC.  

Важно разобраться, почему перестало хватать числа процессов ? Если это естественный рост числа клиентов, то нормально, но я встречался с ситуацией, когда после перезапуска firewall, все клиенты теряли соединение, и заходили вновь. А Oracle не был настроен на DCD, таким образом появлялось в 2 раза больше сессий чем обычно. 

Что это за магия в 1-2 минуты ? Я думаю, что это время, необходимое PMON на определение что сессия была удалена и освобождение ресурсов, с ней связанных.

Q:  Как удалить сервисы из NT ?

A:  В regedit   HKEY_LOCAL_MACHINE--->SYSTEM--->CURRENTCONTROLSET--->SERVICES удалить папку с именем мешающего Вам сервиса.

Dsvolk > > Oracle > > Faq > > Dba Last Modified: 26-08-2004 21:48