private static void acquireBootstrapLock(final ConnectionConfig connectionConfig,
                                             final Configuration txnConfig) {
        LOGGER.info("Waiting to acquire bootstrap lock on table: {}, id: {}, user: {}, url: {}",
                BUILD_VERSION_TABLE_NAME,
                BUILD_VERSION_TABLE_ROW_ID,
                connectionConfig.getUser(),
                connectionConfig.getUrl());
        final Instant startTime = Instant.now();

        final String sql = LogUtil.message("""
                SELECT *
                FROM {}
                WHERE id = ?
                FOR UPDATE""", BUILD_VERSION_TABLE_NAME);

        boolean acquiredLock = false;
        while (!acquiredLock) {
            try {
                // Wait to get a row lock on the one record in the table
                DSL.using(txnConfig)
                        .execute(sql, BUILD_VERSION_TABLE_ROW_ID);
                LOGGER.info("Waited {} to acquire bootstrap lock",
                        Duration.between(startTime, Instant.now()));
                acquiredLock = true;
            } catch (Exception e) {
                // If the node that gets the lock has to run lengthy db= migrations it is almost certain
                // that we will get a lock timeout error so need to handle that and keep trying to get the lock
                if (e.getCause() != null
                    && e.getCause() instanceof MySQLTransactionRollbackException
                    && e.getCause().getMessage().contains("Lock wait timeout exceeded")) {
                    LOGGER.info("Still waiting for bootstrap lock, waited {} so far.",
                            Duration.between(startTime, Instant.now()));
                } else {
                    LOGGER.error("Error getting bootstrap lock: {}", e.getMessage(), e);
                    throw e;
                }
            }
        }
    }
Use a table lock on a noddy table created just for this purpose to enforce
a cluster wide lock so we can do all the flyway migrations in isolation.
Flyway migrations should work under lock but we have lots of independent flyway
migrations so it is safer to do it this way.
Can't user the cluster lock service as that is not a thing at this point.
stroom-app/src/main/java/stroom/app/BootstrapUtil.java