Browse Source

Merge 0ec33f11b6 into c349342ac1

pull/14901/merge
Andrii Landiak 6 days ago
committed by GitHub
parent
commit
7df6ee0558
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 90
      application/src/main/data/upgrade/basic/schema_update.sql

90
application/src/main/data/upgrade/basic/schema_update.sql

@ -25,3 +25,93 @@ ALTER TABLE calculated_field ADD COLUMN IF NOT EXISTS additional_info varchar;
ALTER TABLE rule_chain ADD COLUMN IF NOT EXISTS notes varchar(1000000);
-- RULE CHAIN NOTES MIGRATION END
-- CLEANUP ORPHANED OTA PACKAGE LARGE OBJECTS START
-- Cleans up orphaned PostgreSQL large objects no longer referenced by ota_package.
-- These accumulate when OTA packages are deleted or updated and can consume significant disk space.
-- Note: only the ota_package.data column uses PostgreSQL large objects (OID type) in ThingsBoard.
-- This script removes all large objects not referenced by ota_package.data.
-- If external applications sharing this database also use large objects, their objects WILL be deleted.
--
-- Processes orphans in batches with a COMMIT between each batch. Does not block ota_package
-- (only row-level locks on pg_largeobject rows being deleted), so it is safe to run on a live
-- server. Each batch releases row locks, flushes WAL, and advances the xmin horizon.
CREATE OR REPLACE PROCEDURE cleanup_orphan_ota_lobs(batch_size int DEFAULT 500)
LANGUAGE plpgsql AS
$$
DECLARE
orphan_oid bigint;
batch_processed int;
deleted bigint := 0;
failed bigint := 0;
total_orphans bigint;
start_ts timestamptz := clock_timestamp();
elapsed_sec numeric;
BEGIN
DROP TABLE IF EXISTS orphan_ota_lob_queue;
CREATE TEMP TABLE orphan_ota_lob_queue (oid bigint PRIMARY KEY) ON COMMIT PRESERVE ROWS;
INSERT INTO orphan_ota_lob_queue
SELECT m.oid
FROM pg_largeobject_metadata m
LEFT JOIN ota_package p ON p.data = m.oid
WHERE p.data IS NULL;
SELECT COUNT(*) INTO total_orphans FROM orphan_ota_lob_queue;
IF total_orphans = 0 THEN
RAISE NOTICE 'No orphaned large objects found';
DROP TABLE orphan_ota_lob_queue;
RETURN;
END IF;
RAISE NOTICE 'Found % orphaned large objects, cleaning up in batches of %', total_orphans, batch_size;
COMMIT;
LOOP
batch_processed := 0;
FOR orphan_oid IN
SELECT oid FROM orphan_ota_lob_queue LIMIT batch_size
LOOP
BEGIN
PERFORM lo_unlink(orphan_oid);
deleted := deleted + 1;
EXCEPTION WHEN OTHERS THEN
failed := failed + 1;
RAISE WARNING 'Failed to unlink large object %: %', orphan_oid, SQLERRM;
END;
DELETE FROM orphan_ota_lob_queue WHERE oid = orphan_oid;
batch_processed := batch_processed + 1;
END LOOP;
COMMIT;
EXIT WHEN batch_processed = 0;
elapsed_sec := EXTRACT(EPOCH FROM clock_timestamp() - start_ts);
RAISE NOTICE 'Progress: % deleted, % failed, % remaining (%s elapsed)',
deleted, failed, total_orphans - deleted - failed, ROUND(elapsed_sec, 1);
END LOOP;
DROP TABLE orphan_ota_lob_queue;
elapsed_sec := EXTRACT(EPOCH FROM clock_timestamp() - start_ts);
IF failed > 0 THEN
RAISE WARNING 'OTA large object cleanup finished: % deleted, % failed out of % (%s elapsed)',
deleted, failed, total_orphans, ROUND(elapsed_sec, 1);
ELSE
RAISE NOTICE 'OTA large object cleanup finished: % deleted (%s elapsed)',
deleted, ROUND(elapsed_sec, 1);
END IF;
END;
$$;
CALL cleanup_orphan_ota_lobs(500);
DROP PROCEDURE IF EXISTS cleanup_orphan_ota_lobs(int);
-- CLEANUP ORPHANED OTA PACKAGE LARGE OBJECTS END

Loading…
Cancel
Save