お気づきかもしれませんが、サービス製品としてのフルマネージドデータベースとして、AWS Relational Data Base Service(RDS)はユーザーランドコマンドの実行を制限します。
本番データベースをステージングしていて、pg_largeobject
テーブルは、永続性仮想デバイスの全容量の40%に膨れ上がりました。
PostgreSQLデータベースを実行しているRDSインスタンスでvacuumlo
(他のDBA.SEの質問 here で美しく説明されています)を実行するにはどうすればよいですか?
すべてのクレジットは https://dba.stackexchange.com/a/174664/83878 ですが、私の場合はソリューションを簡略化できました。私の場合、スキーマは1つしかありません。また、最初のステートメントsearch_path = pg_catalog
システムカタログを変更する権限がないため、私の場合は機能しません。単一の命令だけで、リンク解除手順を大幅に簡略化することもできました。
vacuum_lo_removeme
:存在しない場合のテーブルの作成vacuum_lo_removeme AS SELECT oid AS lo FROM pg_catalog.pg_largeobject_metadata
注:これはデフォルトのスキーマで作成されます。
SELECT c.relname as tablename, a.attname as columnname FROM pg_class c, pg_attribute a, pg_namespace s, pg_type t WHERE a.attnum > 0 AND NOT a.attisdropped AND a.attrelid = c.oid AND a.atttypid = t.oid AND c.relnamespace = s.oid AND t.typname in ('oid', 'lo') AND c.relkind in ('r','m') AND s.nspname !~ '^pg_' AND relname != 'vacuum_lo_removeme'
DELETE FROM vacuum_lo_removeme WHERE lo IN (SELECT ${columnname} FROM ${tablename}
例:ここでJava=を使用しています(rs
は前のステートメントのResultSetです):
while (rs.next()) {
String tablename = rs.getString("tablename");
String columnname = rs.getString("columnname");
// remove OID which must be kept
String removeUsedOids = String.format("DELETE FROM vacuum_lo_removeme WHERE lo IN (SELECT \"%s\" FROM \"%s\")",
columnname, tablename);
stmt = connection.createStatement();
stmt.executeUpdate(removeUsedOids);
}
SELECT count(lo_unlink(lo)) from vacuum_lo_removeme where lo in (select loid from pg_catalog.pg_largeobject)
DROP table vacuum_lo_removeme