четверг, 14 апреля 2016 г.

Ядро oracle

на основе одноименной книги Дж. Льюиса

1. Согласованное чтение
2. Восстановление данных
3. Принцип кэширования блоков в память при чтении
4. Парсинг запросов
5. RAC - кластер экземпляров oracle
6. Блокировки и защелки


1. согласованное чтение
общий принцип:

a. транзакция 1 изменяет данные:
 * в буферный кэш скидывается грязный блок
  ** в блоке данных записывается список недавних транзакий ITL (включая сейчас выполняющуюся)
  ** если транзакция сейчас выполняется, то также проставляется признак блокировки строки в блоке
 * процесс lgwr пишет:
  ** в redo журнал повтора - новое значение, новый scn, список ITL
  ** в undo журнал отката - старое значение и старый scn
 * процесс dbwr пишет:
  ** асинхронно с задержкой записывает данные в блок базы
   *** сразу после commit записывается не более 30% данных
   *** остальная часть записывается отложенно при следующем select из строк этой таблицы.
   Детектировать можно через события "db block change, consisten gets - examination"
   Т.е. не стоит удивляться, что первый select после большого update будет выполняться очень долго.

b. транзакция 2 читает данные:
 * считываются данные из буферного кэша или напрямую с диска
 * просматривается список ITL на наличие незавершенных транзакций
 * в любом случае (не зависимо от ITL) сверяется SCN транзакции и SCN блока (ITL незавершенной транзакции)
  ** если SCN блока/ITL оказывается больше запрашиваемого, то данные берутся из сегментов отката UNDO через ссылку из ITL
   *** поиск по ITL может продолжиться и дальше рекурсивно, если SCN запроса опять меньше SCN из undo
   *** если данные в undo не находятся, то это является причиной ошибки "snapshot too old"
 * в случае недавнего обновления блока, строка может оказаться помеченной как сейчас обновляемая и со старым SCN в списке ITL выполняется операция отложенная очистка:
  ** берутся данные из UNDO сегмента, смотрится, что транзакция подтверждена
  ** сбрасывается флаг блокировки в строке блока и ITL (что повторно генерирует redo логи при select таблицы)
  ** в случае отсутствия блока в буферном кэше и чтения с диска дополнительно изменяется номер SCN на максимальный (т.к. отсутствие блока в кэше говорит об однозначно последней версии на диске)

Примечание: как многоверсионность сделана в Postgree:
Устаревшие строки (после delete/update) хранятся в том же месте, где основная таблица.
Определение версии используются дополнительные идентификаторы в самой строке.
При update выполняются действия:
* Создается строка с новыми данными
* От старой строки создается указатель на новую
* У старой строки проставляется:
 ** xmin - идентификатор транзакции от старой версии строки
 ** xmax - идентификатор транзакции от новой версии строки

Т.е. при select читаются строки у которых нет новой версии (xmax), т.е. актуальные сейчас строки. Если в этот момент идет модификация, то старые строки будут существовать до полного окончания, а после будут очищены фоновым vacuum.

+ быстрое чтение, без обращения к стороннему логу
- любое изменение генерирует новую строку, из-за чего нужно перестраивать все индексы на таблице, даже если изменялось поле не из индексов
- большой поток изменений в репликации