Очистка блоков данных

dbstalker, 10 сентября

Иногда, после выполнения большого объема изменений в таблице, выборка информации из неё занимает неожиданно много времени. К тому же выясняется, что на выполнение этой команды SELECT почему-то были сформированы данные повторного выполнения (redo). Почему такое происходит и как с этим бороться?

Как оказалось, во всем виновата отложенная очистка блоков данных(Delayed logging block cleanout). Я изложу все, как я себе это представляю.

Предположим, нам нужно обновить много записей в таблице, а затем выбрать данные из этой таблицы. Процесс в упрощенном варианте будет таковым:

  1. транзакция на обновление начинается
  2. читаются блоки в sga
  3. Изменяются блоки данных.
  4. В заголовке сегмента отката в слоте для нашей транзакции занесена информация, что наша транзакция еще не зафиксирована.
  5. В заголовке блоков данных ставится указатель на сегмент отката где хранятся данные отката по нашим изменениям + слот ( так устанавливается связь между блоком данных и сегментом отката)
  6. некоторые измененные блоки данных могут быть сброшены на диск
  7. команда commit
  8. В заголовке сегмента отката в слоте для нашей транзакции занесена информация о том, что наша транзакция зафиксирована.
  9. в те блоки данных, которые были уже сброшены на диск, изменения не вносятся, т.е. блоки заново не читаются в sga.
  10. к тем блокам данных, которые ещё в sga , повторно обращается сервер и очищает их от информации о нашей транзакции
  11. транзакция завершена.
  12. потребовалось прочитать некоторые измененные блоки
  13. если блок чистый, то он только читается и все.
  14. если блок грязный (в заголовке есть информация о последней транзакции), то из заголовка выбирается информация о сегменте отката и слоте
  15. по этой информации находится сегмент отката
  16. в нашем слоте сегмента отката читается информация о том, что транзакция была зафиксирована
  17. блок данных очищается.
  18. бывший грязный блок также попадает в нашу выборку.

То есть те блоки, что ещё находились в sga, почистились сразу во время фиксации транзакции (очистка при фиксации), а те, что уже были сброшены на диск, будут очищены при следующем чтении этих блоков (отложенная фиксация транзакций).

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

Поэтому, во избежание недоразумений, всегда очень полезно после больших изменений в таблице собрать статистику(команда ANALYZE). Это избавит вас от непредвиденных потерь времени в неподходящий момент.

вот здесь прекрасный демонстрационный пример.

Чтобы не потерялось, копирую для вас и для себя  ценную статью.

http://www.ixora.com.au/q+a/cr.htm
delayed_logging_block_cleanouts 	 
What does the delayed_logging_block_cleanouts parameter do? 

 	We need a bit of terminology to discuss this. A block cleanout is an operation to release the row-level locks that were held by a transaction. Row-level locks consist of a pointer in the row header to an entry in the interested transaction list (ITL) in the variable header of the block. In a cleanout, the row level locks may be cleared and the commit SCN of the transaction is recorded in the ITL. The term commit cleanout refers to cleanouts of just the ITL entry performed by the transaction itself when it commits. The term delayed block cleanout refers to cleanouts performed later by another transaction. 

As a transaction modifies blocks, the buffer header addresses are recorded in a commit cleanout data structure, which can hold pointers to up to 10% of the buffers in the cache. When the transaction commits, it traverses its commit cleanout data structure in reverse order and cleans out its ITL entries. The commit cleanout of a block can fail if the block has already been written to disk, or for several other reasons. If a commit cleanout fails for any reason, then the block is written to disk with the ITL and row-level locks not yet cleaned out. This is where delayed block cleanout comes in. 

Delayed block cleanout is performed by the next reader of the block, even if it is just a query. The block is read into the cache as a current mode block and cleaned out. If a query is being performed, a consistent read mode clone of the block is made using another block buffer, and if necessary rolled back to the snapshot SCN for the query. The consistent read mode buffer is used to satisfy the query. However, any changes are made to the current mode buffer. 

Because block cleanout actually makes changes to the current mode buffer, it must generate redo. If delayed_logging_block_cleanouts is TRUE, which is the default in 7.3 and 8.0, the logging of this redo is delayed until another change is made to the current buffer. The cleanout itself does not mark the buffer as dirty or log the redo for its changes. The next change to the buffer marks the buffer as dirty and logs redo for the cleanout as well as its own changes. 

If the parameter is FALSE, the cleanout logs its own redo and marks the buffer as dirty, even if the block was only being used for a query. Because the buffer is dirty, DBWn must write the cleaned out block back to disk. This increases DBWn's workload, but prevents the cleanout from having to be repeated by later queries. The cost of a cleanout is low, relative to a write, but not trivial, because it takes a buffer lock on the buffer containing the rollback segment header block for the old transaction, and that can be a "hot" block. 

Delayed logging block cleanouts save pings against data blocks in parallel server databases, at the expense of some extra pings against rollback segment header blocks. So, in general for OPS databases the parameter should be left to default to TRUE. However, if you have data that is queried intensively, but seldom changed, then it may be beneficial to temporarily set the parameter to FALSE and force a serial full table scan after each change. The full scan has to be serial, because parallel scans do direct reads, so the cleanouts are done in private buffers in the PGAs of the parallel query slaves, where the cleaned out blocks cannot be written back to disk by DBWn. 

This parameter was introduced in release 7.3 in an attempt to reduce pings in OPS databases. It has however been removed from release 8.1, having been obviated by cache fusion. 

 
  	Delayed block cleanout 	Why would delayed block cleanout be needed on a table that is only ever queried and never updated? 

 	Every data block that is needed for the query will have been changed by at least one transaction at some point in the history of the database. If the row-level locks required for the last (possibly ancient) transaction to modify the block were not able to be cleaned out at the time, and if delayed_logging_block_cleanouts is TRUE (which is the default) then all subsequent queries will need to perform delayed block cleanout until another transaction modifies the block and cleans out the old row-level locks permanently.

 

Новый комментарий

Я не спамер: введите суму 6+3



 

От авторов блога

О Блоге - прочитай перед началом.

Задать вопрос и получить ответ - уже решено 94 вопросов

Глоссарий - список терминов и сокращений


 
 

Бизнес форум

Последние темы:

Микрофон
19 августа, 2 ответа
Сумочка
19 августа, 2 ответа
средства для рук
17 августа, 3 ответа