TL;DR
Если это СУБД с гитхаба, то никак.
Зачем вообще "надёжно" стирать данные? Главное же, чтобы пользователь через интерфейс СУБД не мог их достать. Мало ли, что там за остатки данных в файлах болтаются, это же не проблема. Или нет?
Вообще утечки данных через память и файлы иногда встречаются. Из-за этого есть требование затирать переменные, в которых хранились пароли или ключи. В таких ситуациях оптимизирующие иногда компиляторы добавляют багов, удаляя memset для буфера, который больше не используется.
А для баз данных, к примеру, есть требование ФСТЭК:
13.1. Система управления базами данных 6, 5 классов защиты самостоятельно или с применением сертифицированной операционной системы должна обеспечивать удаление баз данных и журналов, используемых системой управления базами данных, путем многократной перезаписи уничтожаемых (стираемых) объектов файловой системы специальными битовыми последовательностями.
Получается, что (сертифицированные) СУБД должны не просто помечать записи, как удалённые, но и перезаписывать удаляемые данные во всех местах, куда они были сохранены.
Нас заинтересовала эта тема, и мы решили потестировать публично доступные СУБД на предмет того, удаляют ли они данные, или что-то остаётся. И так как мы разрабатываем Natch - инструмент поиска поверхности атаки, то все проблемы выглядят как гвозди решили с помощью него исследовать потоки данных в СУБД.
Ведь работа с чувствительными данными и поиск утечек мало отличается от работы с недоверенными данными и поиска поверхности атаки.
Идея тестирования была такая:
Создаём базу данных.
Записываем туда "чувствительные" данные.
Отслеживаем поток этих данных в системе.
Удаляем данные средствами СУБД.
Проверяем те места, куда в п.3 данные попали, по-прежнему они там или нет.
Пишем статью на хабр.
PostgreSQL
Для того, чтобы проверить, удаляются ли данные, нужно понять, где они вообще хранятся. Конечно же, сначала надо создать базу данных:
CREATE DATABASE my;
USE my;
CREATE TABLE mytable (col text);
Natch умеет отслеживать "чувствительные" данные, поступающие из сети, или считанные из файла. Тогда можно либо подключаться к СУБД удалённо, помечая сетевой трафик (который и будет содержать добавляемые в базу данные). Либо записать команду INSERT в файл, и помечать для отслеживание уже содержимое файла.
Мы применяли второй способ, поэтому запускали PostgreSQL под контролем Natch, передавая в СУБД файл pg_insert.sql со следующим запросом:
INSERT INTO mytable VALUES (‘dhfgkjhewdrtg;kljhwekjthekjthkjwehtkjhertkjhewrkjthekjthkjwerhtkjhertkjhekljthekjgkjdsngkjnikjuh43kiujhtkj3ntkj3j3ntkj34hnrtkjh 3kjhtk3hrlkj oruq97g98weytg nui3ht k3h4trkhglkeoi;tru 8o934urowjrh qwtuikh3489tuyoiktghiljpoqwro;iwotrhyt’);
Добавляемая строка не очень случайная, но нам повезло, и она не сильно подверглась компрессии в хранилище. В итоге, Natch определил, что вставленные в таблицу данные осели в файлах data/base/16389/16390 и data/pg_wal/000000010000000000000001.

В первом файле хранятся сами данные строк таблицы, а второй - это write-ahead log (WAL). Это журнал изменений, который используется, по меньшей мере, для восстановления БД после сбоев.
Теперь, когда мы будем удалять данные, нужно убедиться, что они пропали из обоих файлов. Ведь это чувствительные данные, не хочется их разбрасывать где попало.
Тут уже понадобится небольшая хитрость. Ведь Natch отслеживает данные, пока они куда-то перемещаются или где-то обрабатываются. Но если данных больше нет, что он может показать? Для решения этой проблемы можно просто обратиться к содержимому файлов, где хранились чувствительные данные (с помощью find, grep или даже md5sum). И тогда либо мы увидим нужный паттерн в логе файловых транзакций, либо на диаграмме процессов появится стрелочка с передачей чувствительных данных в новый процесс.
Почему стрелочка может не появиться?
Дело в том, что Natch пока что не отслеживает распространение помеченных данных на дисковых накопителях. Поэтому если что-то записать на диск, а потом прочитать заново, то пометки будут потеряны.
Но если ОС оптимизирует этот процесс, и после записи сохранит данные в кэше в ОЗУ, то и пометки для них тоже сохранятся. В таких ситуациях поток данных Natch отслеживает успешно.
Итак, попробуем удалть данные из таблицы, а потом посчитать md5 для интересующих нас файлов. Утилита md5sum вынуждена будет прочитать все данные из файлов, а нам только это и нужно.
DELETE FROM mytable;
Команда DELETE наверняка не удаляет строки физически. Для полного удаления придётся сделать что-то ещё. Проверим эту гипотезу.

Файловые транзакции даже не пришлось смотреть, все данные оставались в кэше ОС. И действительно, из таблицы удалённые строчки не пропали. Но есть ещё команда VACUUM. Она-то точно удалит всё лишнее.

Данные всё ещё там, в WAL. Правда, уже в новом файле. А непосредственно из таблицы действительно всё удалилось.
Как ещё можно повлиять на БД? Удалить её целиком. Уж теперь-то точно всё должно пропасть.
DROP DATABASE my;
VACUUM FULL;
Для верности остановим СУБД, чтобы точно ничего не осталось в памяти. Ну и проверим, на месте ли добавленные данные, только в этот раз с помощью grep, а не md5sum:
systemctl stop postgresql
cd /usr/local/pgsql/data/base
grep -r oruq97g98

Итак, СУБД была остановлена, вся база удалена, а "чувствительные" данные не только остались в файле, но ещё и висели в файловом кэше ОС.
MySQL
Следующая СУБД для исследования - MySQL. С ней будем делать примерно то же самое. Сначала выясним, в какие файлы попадут наши данные после INSERT:

Тут, как и в postgres, кроме файла с таблицей, есть и дополнительные файлы с транзакциями - binlog и redo log.
Проверим, что будет после удаления данных из таблицы:
DELETE FROM mytable;
FLUSH TABLES;
FLUSH BINARY LOGS;
FLUSH ENGINE LOGS;

Данные ожидаемо сохранились в логах транзакций. Оказывается, binlog можно подчистить с помощью команды RESET BINARY LOGS AND GTIDS.

Остался redo log. Удаляем БД.

И опять из лога изменений данные стереть не удалось.
MariaDB
Третий наш испытуемый - СУБД MariaDB. Сначала выясняем, где хранятся добавляемые в таблицу данные.

Natch показывает запись только в logfile. Это довольно странно, потому что должен же ещё быть файл с таблицей. Погрепаем нашу строку-паттерн в /var/lib/mysql, где лежит и этот logfile, и другие файлы mariadb.

Действительно, есть и таблица, и ещё какой-то дополнительный файл. Что там прочитал grep, можно проверить с помощью Natch:

Особенность Natch в том, что потоки данных отслеживаются в первую очередь внутри программ и между ними. Данные на диске же напрямую пока не отслеживаются, поэтому если они записались не через системный вызов write, а например, через fsync, то стрелочка на диаграмме не появится. Тем не менее, исследовать работу СУБД всё же получается, хоть и применяя вспомогательные утилиты.
Теперь попробуем удалить данные из БД с помощью команды DELETE. После удаления, останавливаем сервис СУБД и делаем grep. Поток данных из ib_logfile0 в grep не обнаружился, значит MariaDB умеет делать так, чтобы ОС не кэшировала данные этого файла в памяти.

Так как Natch не видит grep на графе, посмотрим логи операций с файлами.

Удивительно, что данные из таблицы пропали после обычного DELETE. Теперь попробуем удалить всю БД с помощью команды DROP DATABASE.
Получилось всё то же самое. Файлов с таблицами уже нет на диске, а данные в ib_logfile0 остались. Всё, как и в остальных СУБД, "чувствительные" данные хоть где-то, да сохраняются. Так что у MariaDB отличается только стратегия работы с файлами таблиц.
Заключение
Оказывается, сертифицированные и enterprise-версии открытых продуктов существуют не просто так. Ни одна из проверенных свободных СУБД не позволяет вычистить удаляемые данные изо всех файлов. Поэтому, если вы строите сертифицируемую систему, просто так взять и установить СУБД из какого-нибудь debian-репозитория не выйдет.