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

Очистка высвобождаемого дискового пространства

В СУБД Pangolin реализована функциональность по очистке памяти в процессе работы СУБД, осуществляющая перезапись высвобождаемого дискового пространства специальными последовательностями блоков. Функциональность обеспечивает исключение рисков утечки данных.

Описание​

Очистка удаляемых файлов данных происходит для операций:

  • DROP TABLE;
  • DROP MATERIALIZED VIEW;
  • DROP TEMPORARY TABLE;
  • DROP INDEX;
  • TRUNCATE;
  • DROP DATABASE;
  • REINDEX;
  • DROP SCHEMA;
  • VACUUM FULL;
  • ALTER TABLE ADD COLUMN (с изменчивым значением по умолчанию, при этом таблица записывается в новые файлы);
  • ALTER TABLE ALTER COLUMN TYPE (перезапись таблицы в новый файл происходит, если преобразование полей требует изменения формата данных).

Также очистка происходит при удалении содержимого WAL-файла.

примечание

При выполнении операции BEGIN → DROP TABLE/INDEX/MATERIALIZED VIEW ... → ROLLBACK очистка файлов не производится.

Очистка удаляемых или высвобождаемых WAL-файлов происходит в результате операций:

  • Удаления файлов средствами операционной системы;
  • CHECKPOINT.

Особенности реализации​

В данной реализации изменено поведение по сравнению с оригинальным ядром PostgreSQL. Добавлен дополнительный этап перезаписи файлов нулевыми значениями — блоками такой длины, чтобы предотвратить их немедленное освобождение операционной системе. Это позволяет сохранить занимаемое дисковое пространство до момента выполнения контрольной точки (CHECKPOINT), оптимизируя взаимодействие с подсистемой хранения.

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

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

Данный алгоритм не вмешивается в работу подсистемы виртуальной файловой системы (VFS), и, следовательно, при выполнении перезаписи старые блоки могут быть освобождены операционной системой. Это особенно вероятно, при активированном механизме оптимизации освобождения неиспользуемых блоков (TRIM), который в некоторых системах работает более агрессивно.

Настройка​

В СУБД Pangolin предусмотрено включение и отключение данной функциональности. Настройка происходит с помощью конфигурационных параметров.

Параметры хранятся в различных файлах:

  • для standalone-конфигурации — в файле postgresql.conf;
  • для кластерной конфигурации — в файле postgres.yml.

Включение функциональности происходит раздельно: отдельно включается функциональность, касающаяся WAL-файлов и отдельно файлов представлений.

Конфигурационные параметры​

ПараметрОписаниеЗначение по умолчаниюВозможные значения
nonrestorable_deletionОчистка удаляемых файлов данныхoffon/off
nonrestorable_wal_deletionОчистка удаляемых или высвобождаемых WAL-файловoffon/off

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

Для применения параметров необходимо выполнить перезапуск (restart) кластера СУБД.

Диагностика​

В случае неуспешной попытки перезаписи файла, в лог генерируется сообщение вида:

WARNING: could not erase file

Сценарии использования​

Проверка удаления содержимого файла с данными материализованного представления после выполнения команды DROP MATERIALIZED VIEW​

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

Предусловия​

  1. Активируйте настройку nonrestorable_deletion:

    1. Установите параметр настройки хранилища секретов secure_config в значение off.

    2. Подключитесь к базе данных и убедитесь, что параметр nonrestorable_deletion виден базе данных и имеет нужное значение (по умолчанию off):

      postgres=# SHOW nonrestorable_deletion;

      Ожидаемый результат: Параметр виден, его значение - off:

      nonrestorable_deletion
      ----------------------------
      off
      (1 row)
    3. Установите параметр nonrestorable_deletion в значение on (в случае кластерной конфигурации необходимо установить значение параметра также на реплике):

      postgres=# ALTER SYSTEM SET nonrestorable_deletion = 'on';

      Ожидаемый результат: Параметр успешно изменен:

      ALTER SYSTEM
    4. Перезапустите кластер (restart), чтобы значение параметра изменилось для всего кластера:

      postgres=# exit
      $ sudo systemctl restart postgresql/pg_ctl restart

      Ожидаемый результат: Кластер успешно перезапущен, ошибок нет:

      pg_reload_conf
      ----------------
      t
      (1 row)
    5. Проверьте значение параметра nonrestorable_deletion:

      postgres=# SHOW nonrestorable_deletion;

      Ожидаемый результат: Параметр имеет значение on:

      nonrestorable_deletion
      ----------------------------
      on
      (1 row)
  2. Создайте директорию, где будут храниться жесткие ссылки файлов с данными объектов тестовой базы данных (в случае кластерной конфигурации необходимо создать папку с идентичным названием также на реплике):

    $ mkdir /pgdata/0{base_version}/tablespaces/hardlinks_db_objects
  3. Создайте табличное пространство test_tablespace, в котором проинициализирована тестовая база данных (в случае кластерной конфигурации необходимо создать папку с идентичным названием также на реплике):

    $ mkdir /pgdata/0{base_version}/tablespaces/test_tablespace
    $ psql
    postgres=# CREATE TABLESPACE test_tablespace LOCATION '/pgdata/0{base_version}/tablespaces/test_tablespace';
    postgres=# CHECKPOINT;
  4. Создайте в тестовом табличном пространстве тестовую базу данных test_db, подключиться к ней:

    postgres=# CREATE DATABASE test_db TABLESPACE test_tablespace;
    postgres=# \c test_db
  5. Установите путь до каталога с файлами БД:

    postgres=# SHOW data_directory; --> /pgdata/0{base_version}/data/
  6. В тестовой базе данных создайте тестовую таблицу с записями, состоящими из сгенерированных строк случайным образом длиной 255 символов и содержащими контрольную последовательность CARDnumber888825101204PiN1945 в начале, середине и конце каждой строки. Для очистки буфера и записи данных на диск выполните в конце каждой операции контрольную точку (CHECKPOINT):

    test_db=# CREATE TABLE test_table AS(SELECT generate_series(1, 3) id, 'CARDnumber888825101204PiN1945hivBZQaygHe7aK4vG4jirGXVaWDW3qs8CVCARDnumber888825101204PiN1945BXAUX9dE0oeHbu0ZlHIcQ1peOAn8zy9MffMgOsvfKMdatTemeVrt5XJ1k9jAFXCARDnumber888825101204PiN1945' test_data);
    test_db=# CHECKPOINT;

Шаги проверки​

  1. Создайте материализованное представление и наполните чувствительной информацией. Пример команды создания:

    test_db=# CREATE MATERIALIZED VIEW matview_test_table AS SELECT * FROM test_table;
    SELECT 3
  2. Выполните контрольную точку, чтобы файл с данными сохранился на жестком диске:

    test_db=# CHECKPOINT;
    CHECKPOINT
  3. Укажите путь к файлу, в котором хранятся данные материализованного представления:

    test_db=# SELECT pg_relation_filepath('matview_test_table');

    Путь к файлу с данными материализованного представления получен:

    pg_relation_filepath
    ----------------------
    /pgdata/0{base_version}/tablespaces/test_tablespace/1450/1452
  4. Выйдите из БД и из командной строки создайте жесткую ссылку на файл, в котором хранятся данные материализованного представления:

    test_db=# exit
    $ ln /pgdata/0{base_version}/tablespaces/test_tablespace/1450/1452 /pgdata/0{base_version}/tablespaces/hardlinks_db_objects/1452

    Ожидаемый результат: Жесткая ссылка на файл с данными материализованного представления успешно создана.

  5. Подключитесь к тестовой БД, удалите материализованное представление и выполните контрольную точку:

    $ psql
    postgres=# \c test_db
    DROP MATERIALIZED VIEW matview_test_table;
    CHECKPOINT;

    Ожидаемый результат: Материализованное представление успешно удалено:

    DROP MATERIALIZED VIEW
    CHECKPOINT
  6. Выйдите из БД и убедитесь, что файл материализованного представления удален, а жесткая ссылка имеет размер файла больше нуля:

    test_db=# exit
    $ ls -lh /pgdata/0{base_version}/tablespaces/test_tablespace/1450/1452
    $ wc -c /pgdata/0{base_version}/tablespaces/hardlinks_db_objects/1452

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

    ls: cannot access /pgdata/0{base_version}/tablespaces/test_tablespace/1450/1452: No such file or directory
    8192 /pgdata/0{base_version}/tablespaces/hardlinks_db_objects/1452
  7. Найдите данные из удаленного материализованного представления через жесткую ссылку:

    $ grep -b CARDnumber888825101204PiN1945 /pgdata/0{base_version}/tablespaces/hardlinks_db_objects/1452

    Ожидаемый результат: Данные не найдены:

    $