vacuumlo
Утилита для удаления потерянных больших объектов.
Утилита
vacuumlo
представляет собой утилиту, которая удаляет все «потерянные» большие объекты (LO, Large Objects) из базы данных PostgreSQL. Потерянным считается такой объект, OID которого не фигурирует ни в одном из столбцов oid
или lo
.Если в работе появляется необходимость применения утилиты
vacuumlo
, следует обратить внимание на триггер lo_manage
в модуле lo. Триггер lo_manage
полезен возможностью предотвратить потерю больших объектов.Обработке подвергаются все базы данных, перечисленные в командной строке при запуске утилиты.
Утилита
vacuumlo
принимает следующие аргументы командной строки:Аргумент | Описание |
---|---|
-l предел --limit=предел | Максимальное количество больших объектов, которые следует удалять в пределах одной транзакции. Сервер запрашивает блокировку для каждого удаляемого большого объекта, поэтому удаление слишком большого количества больших объектов в одной транзакции может привести к превышению лимита, заданного параметром СУБД max_locks_per_transaction .Значение 0 задает режим, при котором все удаления будут происходить в одной транзакции.Значение по умолчанию – 1000 |
-n --dry-run | Пробный (тестовый) прогон; улитита не будет ничего удалять, а только покажет, какие операции должны будут выполняться |
-v --verbose | Вывод подробного сообщения о прогрессе |
-V --version | Вывод версии утилиты |
-? --help | Вывод справки об аргументах командной строки утилиты |
-h сервер --host=сервер | Параметр подключения: адрес сервера баз данных |
-p порт --port=порт | Параметр подключения: порт сервера баз данных |
-U имя_пользователя --username=имя_пользователя | Параметр подключения: имя пользователя, под которым производится подключение |
-w --no-password | Параметр подключения: Не выдавать запрос на ввод пароля. Если сервер требует аутентификацию по паролю, который недоступен с помощью специальных средств (утилита pg_auth_config или файл .pgpass ), попытка соединения будет неудачной. Этот параметр может использоваться в пакетных заданиях и скриптах, где нет пользователя, который вводит пароль |
-W --password | Параметр подключения: Принудительно запрашивать пароль перед подключением к базе данных. Несущественный параметр, так как vacuumlo запрашивает пароль автоматически, если сервер проверяет подлинность по паролю. В этом случае vacuumlo лишний раз подключается к серверу, поэтому для исключения лишней попытки подключения имеет смысл ввести ключ -W |
Параметры подключения по умолчанию:
PGHOST
;PGPORT
;PGUSER
.
Утилита
vacuumlo
использует переменные среды, поддерживаемые libpq. Работает следующим образом:- строит временную таблицу, содержащую все OID больших объектов в выбранной базе данных;
- сканирует все столбцы в базе данных, имеющие тип
oid
илиlo
; - удаляет соответствующие записи из временной таблицы, при этом рассматриваются только типы именно с такими именами, оставшиеся записи во временной таблице указывают на потерянные БО, которые затем и удаляются.
-
Создайте простой файл
lo_file.txt
для импорта в базу данных:echo abcdefghqwerty > /tmp/lo_file.txt
-
Вызовите функцию
lo_import
и передайте имя файла, который требуется загрузить:SELECT lo_import('/tmp/lo_file.txt');
Пример вывода результата выполнения запроса:Раскрыть type=sqllo_import ----------- 19014 (1 row)
В ответ СУБД выдает число – это идентификатор объекта. -
Создайте таблицу и сохраните в ней полученный идентификатор, используйте тип данных
OID
для хранения идентификаторов объектов:CREATE TABLE lo_file (name text, oid_number oid); INSERT INTO lo_file VALUES ('/tmp/lo_file.txt', lo_import('/tmp/lo_file.txt')) RETURNING *;
Пример вывода результата выполнения запроса:Раскрыть type=sqlname | oid_number ------------------+------------ /tmp/lo_file.txt | 19021 (1 row) INSERT 0 1
Большой объект полностью независим от файла в файловой системе. -
Для проверки работы утилиты импортируйте указанный файл большое количество раз, в данном примере - 100 тысяч раз:
INSERT INTO lo_file SELECT '/tmp/lo_file.txt', lo_import('/tmp/lo_file.txt') FROM generate_series(1, 100000);
Проверка результата выполнения запроса:Раскрыть type=sqllo_tst=# SELECT * FROM lo_file LIMIT 10; name | oid_number -----------------+------------ /tmp/lo_file.txt | 19021 /tmp/lo_file.txt | 19022 /tmp/lo_file.txt | 19023 /tmp/lo_file.txt | 19024 /tmp/lo_file.txt | 19025 /tmp/lo_file.txt | 19026 /tmp/lo_file.txt | 19027 /tmp/lo_file.txt | 19028 /tmp/lo_file.txt | 19029 /tmp/lo_file.txt | 19030 (10 rows)
Файл был импортирован. Каждый файл имеет новый идентификатор объекта, как показано в списке. -
Просмотрите внутренние компоненты при помощи системного каталога
pg_largeobject
, чтобы понимать, как данные хранятся в СУБД:lo_tst=# \d pg_largeobject
Вывод результата:Раскрыть type=sqlTable "pg_catalog.pg_largeobject" Column | Type | Collation | Nullable | Default -------+---------+-----------+----------+--------- loid | oid | | not null | pageno | integer | | not null | data | bytea | | not null | Indexes: "pg_largeobject_loid_pn_index" UNIQUE, btree (loid, pageno)
Подробное описание значений столбцов таблицыpg_largeobject
в документации: https://www.postgresql.org/docs/13/catalog-pg-largeobject.html. -
Отобразите массив байтов столбца
data
с типомbytea
:SELECT * FROM pg_largeobject WHERE loid = 19029 ORDER BY pageno;
Пример вывода результата выполнения запроса:Раскрыть type=sqlloid | pageno | data ------+--------+---------------------------------- 19029 | 0 | \x61626364656667687177657274790a (1 row)
Для удобства чтения переведите вывод двоичных данных в форматescape
:SET bytea_output TO escape; SELECT * FROM pg_largeobject WHERE loid = 19029 ORDER BY pageno;
Пример вывода результата выполнения запроса:Раскрыть type=sqlloid | pageno | data ------+--------+-------------------- 19029 | 0 | abcdefghqwerty\012 (1 row)
-
С помощью функции
lo_unlink()
удалите большой объект с OID19029
:SELECT lo_unlink(19029);
Пример вывода результата выполнения запроса:Раскрыть type=sqllo_unlink ----------- 1 (1 row)
Подробное описание функцииlo_unlink()
в документации https://www.postgresql.org/docs/13/lo-funcs.html. -
Запустите утилиту с аргументом
--dry-run
или-n
для проверки количества больших объектов, подлежащих удалению:vacuumlo --dry-run --verbose lo_tst Connected to database "lo_tst" Test run: no large objects will be removed! Checking oid_number in ext.lo_file Would remove 1 large objects from database "lo_tst".
-
Удалите найденный потерянный большой объект:
vacuumlo --verbose lo_tst Connected to database "lo_tst" Checking oid_number in ext.lo_file Successfully removed 1 large objects from database "lo_tst".
-
Убедитесь, что повторная проверка не находит потерянных больших объектов в выбранной базе данных:
vacuumlo --dry-run --verbose lo_tst Connected to database "lo_tst" Test run: no large objects will be removed! Checking oid_number in ext.lo_file Would remove 0 large objects from database "lo_tst".