|
Программирование >> Oracle
измененных блоков не превышает 10 процентов буферного кэша и эти блоки доступны, сервер Oracle очистит их при фиксации транзакции. В противном случае блоки будут просто пропущены (не очищены). Зная это, можно создать искусственные условия для демонстрации того, как происходит очистка. Я установил параметру DB BLOCK BUFFERS небольшое значение - 300. Затем создал таблицу, строка которой занимает блок (т.е. двух строк ни в одном блоке не будет). Затем я вставил в эту таблицу 499 строк и выполнил оператор COMMIT. После этого измерил объем сгенерированных данных повторного выполнения, выполнил оператор SELECT, который обращается к каждому измененному блоку, и измерил объем данных повторного выполнения, сгенерированных оператором SELECT. К удивлению многих, оператор SELECT действительно генерирует в этом случае данные повторного выполнения. Более того, измененные им блоки становятся грязными и снова сбрасываются на диск процессом DBWR. Это происходит вследствие очистки блоков. Затем я выполнил оператор SELECT еще раз, и он больше не сгенерировал данные повторного выполнения (что вполне предсказуемо, поскольку в этот момент блоки - чистые ). tkyte@TKYTE816> create table t 2 (x char(2000) default x1 , 3 у char(2000) default y, 4 z char(2000) default z) 5 / Table created. yte@TKYTE1 insert into t 2 select x,y,z 3 from all objects where rownum < 500 499 rows created. tkyte@TKYTE816> commit; Commit complete. Итак, вот таблица с одной строкой в каждом блоке (при размере блока базы данных 8 Кбайт). Давайте определим объем данных повторного выполнения, сгенерированных при чтении данных: tkyte@TKYTE816> column value new value old value tkyte@TKYTE816> select * from redo size; VALUE 3250592 tkyte@TKYTE816> select * 2 from t 3 where x = y; no rows selected tkyte@TKYTE816> select value-&old value REDO GENERATED from redo size; old 1: select value-&old value REDO GENERATED from redo size new 1: select value- 3250592 REDO GENERATED from redo size REDO GENERATED 29940 tkyte@TKYTE816> commit; Commit complete. Итак, при выполнении оператора SELECT б]ло сгенерировано около 30 Кбайт дан-н1х повторного выполнения. Она представляет заголовки блоков, измененные при полном просмотре таблицы Т. Процесс DBWR в дальнейшем запишет эти измененные блоки на диск. Если теперь выполнить запрос повторно: tkyte@TKYTE816> select value from redo size; VALUE 3280532 tkyte@TKYTE816> select * 2 from t 3 where x = y; no rows selected tkyte@TKYTE816> tkyte@TKYTE816> select value-&old value REDO GENERATED from redo size; old 1: select value-&old value REDO GENERATED from redo size new 1: select value- 3280532 REDO GENERATED from redo size REDO GENERATED Commit complete. то можно убедиться, что данные повторного выполнения не генерируются; все блоки - чистые. Если снова выполнить это1 пример при размере буферного кэша не 300 блоков, а 6000, окажется, что при выполнении обоих операторов SELECT данные повторного выполнения не генерируются: ни один из блоков при выполнении этих операторов не изменился. Так происходит потому, что 499 измененных блоков составляют менее 10 процентов буферного кэша, а наш сеанс - единственный. Ни один другой сеанс не работает с данными, никто не вызывает сброс данных на диск и не обращается к измененным блокам. В реальных системах блоки иногда не очищаются, и это вполне нормально. Чаще всего подобная ситуация встречается при вставке (как б]ло показано выше), изменении или удалении большого количества строк, когда затрагивается много блоков базы данных (при изменении данных объемом более 10 процентов буферного кэша она, определенно, возникнет). Первый же запрос, выполненный к затронутому блоку после этого, сгенерирует немного данных повторного выполнения, сделает блок грязным и, кроме того, может вызвать его перезапись, если процесс уже успел сбросить блок на диск или экземпляр бтл остановлен, что вызвало очистку всего буферного кэша. С этим ничего нельзя поделать. Это нормально и вполне предсказуемо. Если бы сервер Oracle не выполнял такую отложенную очистку блоков, для выполнения оператора COMMIT могло бы потребоваться столько же времени, как и для выполнения самой транзакции. При фиксации пришлось бы повторно обработать каждый затронутый транзакцией блок, возможно, повторно считав его при этом с диска (блок уже мог быть сброшен). Если не учитывать очистку блоков и способ ее выполнения, некоторые события будут казаться загадочными, происходящими без видимой причины. Например, изменен большой объем данных и транзакция зафиксирована. После этого выполняется запрос для проверки результатов. Этот запрос почему-то записывает огромные объемы данных на диск и генерирует большое количество данных повторного выполнения. Это кажется невозможным, если не знать об очистке блоков. Вы пытаетесь кому-то показать это, но ситуация не-воспроизводима, поскольку блоки при повторном запросе - чистые . После этого вы относите ситуацию к разряду необъяснимых загадок . В системах ООТ с такой ситуацией почти никогда не сталкиваются. Все транзакции - короткие и простые. Изменяется несколько блоков, и они тут же очищаются. В хранилище данных, где выполняются множественные изменения данных после загрузки, очистку блоков необходимо учитывать при проектировании. Некоторые операции будут создавать данные в чистых блоках. Например, при выполнении оператора CREATE TABLE AS SELECT, непосредственной загрузке и непосредственной вставке данных создаются чистые блоки. Операторы UPDATE, обычные операторы INSERT или DELETE могут создавать блоки, которые придется очищать при первом чтении. Это может повлиять на работу, если выполняются следующие операции: множественная загрузка нов1х данных в хранилище данных; выполнение изменений всех данных сразу после загрузки (в результате чего создаются блоки, требующие очистки); при этом пользователи запрашивают данные. Необходимо учитывать, что первый запрос, обращающийся к данным, потребует дополнительной обработки, если придется очищать блоки. С учетом этого можно самостоятельно затронуть данные сразу после изменения. Только что загружен или изменен большой объем данных; их надо проанализировать. Возможно, придется создать ряд отчетов, проверяющих выполнение загрузки. В результате блоки будут очищены, и следующем запросу не придется это делать. Еще лучше сразу после множественной загрузки данных обновить статистическую информацию - все равно это придется сделать. Выполнение оператора ANALYZE для обновления статистической информации тоже очистит все блоки.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |