Oracle S4: a non-owner "DML-only" account cannot run the migration at all
- Upgrade
- 26.0.0 → 26.7.3
- Database
- Oracle Database Free (23ai/26ai), release 23.26.2.0.0, container gvenzl/oracle-free:23-slim
- Topology
- single container
- Host
- laptop (Docker 29, Compose 5.5.0)
- Condition
- Engines other than Postgres · DB user without DDL rights
Summary
The S4 "DML-only account" row is now closed on the fourth engine. On Oracle it does not just differ in fix — the whole failure mode is structurally different, because the user IS the schema. Two runs:
- Run A — DML-only (+ synonyms): fails before any Keycloak changeset, at
Liquibase's own changelog-table discovery, with
ORA-01031. Liquibase does not resolve synonyms when checking forDATABASECHANGELOG(a synonym is not a table inUSER_TABLES), so it believes the table is absent and tries toCREATE TABLE KC_DML.DATABASECHANGELOG, which a DML-only account cannot do. - Run B — DML + full
ANYDDL: the same CREATE now fails withORA-00955: name is already used by an existing object— the existing object is the synonym itself. The synonyms that are required to make DML resolve are themselves the obstacle to Liquibase's DDL.
Conclusion: on Oracle there is no privilege-based fix. The MySQL finding ("DDL privileges suffice") does not translate; neither does the Postgres finding ("ownership required, no GRANT confers DROP INDEX"). On Oracle the account Keycloak connects as must simply be the schema owner — a non-owner DML-only account is not a viable migration posture, because Liquibase cannot see the existing schema through synonyms and cannot create its changelog table beside them.
Environment
| Field | Value |
|---|---|
| Keycloak from → to | 26.0.0 → 26.7.3 |
| Database | Oracle Database Free (23ai/26ai), release 23.26.2.0.0, container gvenzl/oracle-free:23-slim |
| JDBC driver | ojdbc17 + orai18n 23.26.0.0.0 in fixtures/providers/ |
| Schema owner | keycloak (DB_DEVELOPER_ROLE, USERS tablespace) — 87 tables, 194 indexes, 0 sequences |
| Account under test | kc_dml — DML grants + private synonyms on all 87 tables (348 grants) |
| Topology | single container |
| Host | laptop (Docker 29, Compose 5.5.0) |
| JVM heap | -Xms1g -Xmx4g |
Procedure
# 26.0.0 schema created by Keycloak as the keycloak owner (87 tables)
./bin/snapshot.sh baseline-26.0.0-oracle-s4
# kc_dml: DML-only account + synonyms (user-is-schema: unqualified names need synonyms)
CREATE USER kc_dml IDENTIFIED BY kc_dml DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS;
GRANT CREATE SESSION TO kc_dml;
-- for each of the 87 tables T owned by KEYCLOAK:
GRANT SELECT,INSERT,UPDATE,DELETE ON keycloak.T TO kc_dml;
CREATE OR REPLACE SYNONYM kc_dml.T FOR keycloak.T;
# run A — DML only
KC_DB_USERNAME=kc_dml ./bin/upgrade.sh 26.7.3 --no-backup # FAILED, 16s
# run B — DML + ANY-* DDL
GRANT CREATE/ALTER/DROP ANY TABLE|INDEX|SEQUENCE|VIEW|SYNONYM|TRIGGER|PROCEDURE TO kc_dml;
docker compose up -d keycloak # FAILED, 6s
Results
| Run | Account rights | Outcome | Error |
|---|---|---|---|
| A | DML only (SELECT/INSERT/UPDATE/DELETE) + synonyms | exit 1, refused to start | ORA-01031 on CREATE TABLE KC_DML.DATABASECHANGELOG |
| B | DML + full ANY DDL + synonyms | exit 1, refused to start | ORA-00955 on the same CREATE — collides with the synonym |
Schema after both runs: keycloak still 26.0.0, 87 tables, 144 changelog rows;
kc_dml has 0 tables and 87 synonyms. Neither run modified the owner's schema.
Run A failure
liquibase.exception.SetupException: An error occurred while attempting to create
the database changelog table. ... 'KC_DML.DATABASECHANGELOG'
ORA-01031: insufficient privileges
[Failed SQL: (1031) CREATE TABLE KC_DML.DATABASECHANGELOG (ID VARCHAR2(255) ...)]
Liquibase checks for the changelog table and does not find
keycloak.DATABASECHANGELOG, because a synonym is not reported as a table by the
catalogue. It concludes the table is missing and tries to create it in the
connection's own schema (KC_DML) — a DDL operation a DML-only account cannot
perform. Note this is earlier than MySQL, where Liquibase found the existing
changelog and only failed trying to ALTER it.
Run B failure
ORA-00955: name is already used by an existing object
[Failed SQL: (955) CREATE TABLE KC_DML.DATABASECHANGELOG (...)]
With CREATE ANY TABLE granted, the same CREATE now clears the privilege check
and collides with the synonym kc_dml.DATABASECHANGELOG. A schema cannot hold a
table and a synonym of the same name, so the very mechanism that made DML resolve
is what blocks Liquibase's DDL.
Verification
| Claim | Evidence |
|---|---|
| DML-only non-owner fails on Oracle | run A ORA-01031 at CREATE TABLE KC_DML.DATABASECHANGELOG ☑ |
| DDL grant does not rescue it | run B ORA-00955 (synonym collision) ☑ |
| Owner schema untouched by both failures | keycloak 26.0.0, 87 tables, 144 changelog rows ☑ |
| Synonyms are the obstacle | kc_dml 87 synonyms, 0 tables ☑ |