Fix Persistent State Database: Orphaned Rows and Slow Service Startup

This affects persistent state databases on Oracle (Runtime 2025.13 and later) and SQLite (Runtime 2025.14 and later).
Persistent state databases running on PostgreSQL, MySQL, MariaDB, or SQL Server are not affected.

With PAS 26.3.1 / xUML Runtime 2026.8 comes a fix that prevents orphaned rows in the persistent state database that lead to slow service startup with SQLite. This Runtime also cleans existing orphans on service startup.
This page describes how to fix the startup scripts manually if you do not want to update the Runtime.

How to check if you are affected

Oracle and SQLite databases grow continuously because not all data is deleted when a persistent state object is deleted: the number of rows in OBJECT_DATA and OBJECT_LOCKS keeps growing. Starting the service gets slower the longer the service runs with an affected xUML Runtime - up to an hour in reported cases.
Runtime behavior is otherwise correct: no wrong data is read, the rows are only dead weight.

Compare the row counts of OBJECTS against OBJECT_DATA and OBJECT_LOCKS. OBJECT_DATA.OBJECT_ID and OBJECT_LOCKS.OBJECT_ID are primary keys, so in a healthy database both counts are at most the count of OBJECTS. Anything above that is leftovers.

Count the number of orphaned rows (SQLite example):

SQL
sqlite3 -header -column <BRIDGE_DATA>/bridge-<SERVICE>/pstate.db "
SELECT (SELECT COUNT(*) FROM OBJECT_DATA
WHERE OBJECT_ID NOT IN (SELECT ID FROM OBJECTS))  AS orphaned_data,
(SELECT COUNT(*) FROM OBJECT_LOCKS
WHERE OBJECT_ID NOT IN (SELECT ID FROM OBJECTS))  AS orphaned_locks;"

How to apply the fix

Overview Depending on Platform Setup

Kubernetes

Kubernetes installations use MariaDB and are not affected.

Docker

  1. Update to PAS 26.3.1.

  2. Upgrade all services to xUML Runtime 2026.8 one by one.

Bridge

Once a service is started with xUML Runtime 2026.8, the obsolete data is removed from the persistent state database.

Patching the SQL scripts manually

If an upgrade is not an option, the SQL scripts can be patched in place in any affected version.

  • DELETE_ORPHANED_OBJECT_DATA.sql

    SQL
    DELETE FROM OBJECT_DATA
    WHERE OBJECT_ID NOT IN (SELECT ID FROM OBJECTS)
    
  • DELETE_ORPHANED_OBJECT_LOCKS.sql

    SQL
    DELETE FROM OBJECT_LOCKS
    WHERE OBJECT_ID NOT IN (SELECT ID FROM OBJECTS)
    

Both files belong in

  • SQLite: <your Bridge program directory>/bridgeserver-<your bridge version>/<your platform>/resource/sql/sqlite/pstate/

  • Oracle: <your Bridge program directory>/bridgeserver-<your bridge version>/<your platform>/resource/sql/oracle/pstate/

Depending on your Runtime version, the files are already there and only need their content replaced, or they are missing and have to be created. A created file works exactly like a shipped one.

Restart the affected xUML service afterwards. At startup the obsolete data is removed and the SQLite file is resized.

Cleaning up an already bloated database

Instead of a cleanup at service startup (which can take some time) you can do it manually:

1 one square blue Stop all instances of the service.

The cleanup statements must not run while a node is working on the persistent state objects.

2 two square blue Run both statements manually.

SQL
DELETE FROM OBJECT_DATA WHERE OBJECT_ID NOT IN (SELECT ID FROM OBJECTS);
SQL
DELETE FROM OBJECT_LOCKS WHERE OBJECT_ID NOT IN (SELECT ID FROM OBJECTS);

3 three square blue SQLite only: Reclaim the disk space.

Deleting rows does not shrink the database file for SQLite - the freed pages are only marked reusable. Run 

sqlite3 <BRIDGE_DATA>/bridge-<SERVICE>/pstate.db "VACUUM;"

This means the disk space comes back under supervision and with the service down, instead of on the next start.

Make sure there is free disk space of roughly the current size of the database file.

4 four square blue Restart the service instance(s).