Перейти к основному содержимому

Кеширования результатов маскирования и сериализации

Описание

Shared Pool — универсальный пул разделяемой памяти, предназначенный для хранения сериализованных бинарных данных, доступных всем серверным процессам СУБД Pangolin (бэкенд-процессам).

В состав продукта включено расширение shared_pool_view для просмотра Shared Pool.

Решение направлено на повышение производительности при повторном использовании результатов вычислений, таких как маскированные SQL-запросы или сериализованные планы выполнения.

Библиотека Shared Pool предоставляется как внутренняя инфраструктура, доступная другим подсистемам СУБД Pangolin (например, модулям маскирования и трассировки планов).

Реализация обеспечивает:

  • безопасный многопроцессный доступ;
  • универсальный API для сохранения и извлечения бинарных данных;
  • эффективное управление памятью без фрагментации.

Общая структура

Shared Pool размещается в разделяемой памяти (shared memory) и представляет собой хеш-таблицу, индексируемую 64-битными целочисленными ключами.

Количество записей задается конфигурационным параметром (GUC) и изменяется только при перезапуске СУБД.

Каждый элемент хранилища Shared Pool включает следующую информацию:

  • уникальный 64-разрядный ключ вместе с рассчитанным значением хеша;
  • адрес области динамически распределяемой памяти (Dynamic Shared Area – DSA), где находятся двоичные данные записи;
  • отметку времени последней операции чтения или изменения (last_access);
  • элемент двустороннего связного списка (необходим для механизма вытеснения наименее используемых данных — LRU);
  • LWLocks для защиты одновременного доступа к ресурсу несколькими потоками.

Настройка

Механизм работы

Поиск записи

Поиск выполняется под разделяемой (shared) блокировкой соответствующей партиции хеш-таблицы.

Операция обеспечивает исключительно чтение структур данных, но при каждом успешном поиске обновляется поле last_access соответствующей записи. Обновление является атомарным и выполняется без захвата эксклюзивных блокировок.

Другие изменения структуры Shared Pool не выполняются на этапе чтения и поиска, включая:

  • обновление LRU-списков;
  • удаление записей;
  • вставку новых элементов.

Алгоритм поиска:

  1. По ключу определяется партиция хеш-таблицы.

  2. Под shared-блокировкой выполняется поиск элемента.

  3. Если запись найдена:

    • возвращается указатель на entry;
    • поле last_access обновляется.

    Если запись отсутствует – возвращается NULL.

Вставка записи

Вставка возможна только если предварительный поиск вернул NULL. Операция вставки выполняется под эксклюзивной блокировкой партиции.

Алгоритм вставки:

  1. Клиент подготавливает бинарные данные для размещения в Shared Pool.

  2. Механизм Shared Pool захватывает эксклюзивную блокировку партиции.

  3. Повторно выполняется поиск по ключу.

    Если запись уже существует – вставка считается успешной, данные клиента не сохраняются. Если записи нет – выполняется попытка вставки.

    Вставка считается успешной, если:

    • в хеш-таблице есть свободное место;
    • или алгоритм вытеснения успешно освободил место;
    • или запись появилась между поисками.

    Вставка считается неуспешной, если пул достиг максимальной вместимости и алгоритм вытеснения не смог освободить место (например, целевая партиция оказалась пустой).

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

Удаление записи (вытеснение)

Удаление записи выполняется только в рамках операции вставки, когда требуется освободить место в хеш-таблице. Прямая операция удаления по инициативе вызывающего кода не предоставляется.

Для выбора записи-кандидата используется приближенный алгоритм LRU:

  1. Для каждой партиции поддерживается собственный двусвязный LRU-список.
  2. При необходимости вытеснения рассматриваются последние четыре элемента списка.
  3. Среди них выбирается запись с минимальным значением last_access.
  4. Запись удаляется из хеш-таблицы и ее ресурсы освобождаются.

Никакие операции чтения не инициируют удаление или изменение структуры LRU. Корректность механизма вытеснения обеспечивается только в функции вставки. Таким образом, удаление происходит только внутри той партиции, в которую выполняется вставка.

Расчет ключей

Shared Pool использует 64-битные ключи, вычисляемые из исходных данных.

Для различных сценариев применяются отдельные стратегии:

  • Маскирование SQL-запросов:

    Ключ формируется на основе структуры запроса, игнорируя константы. Это реализуется путем модификации компонента лексического анализа (scan.l): при разборе запроса литералы не участвуют в формировании ключа, а идентификаторы и ключевые слова добавляют свои значения в итоговую контрольную сумму.

    Таким образом, запросы с одинаковой структурой и разными константами попадают под один ключ, что предотвращает дублирование маскированных строк.

  • Сериализация планов:

    Ключом служит хеш от полного текстового представления плана.