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

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

В СУБД 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

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

    $