--------------------------------------------------------------------
SUMMARY
--------------------------------------------------------------------
On Oracle, any migration that fails after modifying data (a DML
statement that runs, then a PL/SQL row-count check that raises an
error because the actual affected-row-count doesn't match the
expected count) leaves a success=0 row in the Flyway schema history
table. Flyway then refuses ALL further `migrate` attempts against
that schema until `flyway repair` is run manually — even after the
migration file itself has been corrected.
The same migration pattern against PostgreSQL does NOT require
`repair` under an equivalent failure: the failed attempt leaves NO
row in flyway_schema_history at all, because Postgres wraps the
migration + Flyway's own history insert in one fully-transactional,
all-or-nothing unit (Postgres supports DDL transactions). Oracle's
Flyway dialect reports supportsDdlTransactions() = false
categorically, so Oracle never gets this same atomicity — even
though our migrations contain no DDL at all, only DML.
--------------------------------------------------------------------
REPRODUCTION STEPS (Oracle)
--------------------------------------------------------------------
1. flyway.conf:
flyway.outOfOrder=true
flyway.baselineOnMigrate=true
flyway.oracle.sqlplus=false
flyway.executeInTransaction=true (default)
2. Migration script (DML only, no DDL):
DECLARE
l_cnt PLS_INTEGER;
l_expectedCnt PLS_INTEGER;
BEGIN
l_expectedCnt := 2; -- intentionally wrong; actual match count is 1
UPDATE some_table
SET some_column = 'X', updated_at = SYSTIMESTAMP
WHERE id = 123;
l_cnt := SQL%ROWCOUNT;
IF l_cnt IS NULL OR l_cnt != l_expectedCnt THEN
RAISE_APPLICATION_ERROR(-20000, 'incorrect record count - expected ' || l_expectedCnt || ' but modified ' || l_cnt);
END IF;
END;
/
3. Run `flyway migrate`. Result: migration fails as expected
(see error below), and the UPDATE itself is correctly rolled
back (verified: target row unchanged). BUT a success=0 row is
written to flyway_schema_history for this version.
4. Correct the file (l_expectedCnt := 1) and run `flyway migrate`
again, WITHOUT running `flyway repair` first.
Result: Flyway refuses to even attempt the corrected file:
ERROR: Schema "ADMIN" contains a failed migration to version 20260101000006 !
5. Only after running `flyway repair` (which deletes the success=0
row) does the corrected migration get picked up and applied
successfully.
--------------------------------------------------------------------
ACTUAL ERROR OUTPUT
--------------------------------------------------------------------
First (failing) run:
ERROR: Migration of schema "ADMIN" to version "20260101000006 - MISMATCH-TEST" failed! Please restore backups and roll back database and code!
ERROR: Failed to execute script V20260101000006__MISMATCH-TEST.sql
-----------------------------------------------------------------
SQL State : 72000
Error Code : 20000
Message : ORA-20000: incorrect record count - expected 2 but modified 1
ORA-06512: at line 24
Location : ./oracle/admtest/public/V20260101000006__MISMATCH-TEST.sql
Line : 6
Retry attempt (corrected file, no repair run):
Current version of schema "ADMIN": 20260101000005
outOfOrder mode is active. Migration of schema "ADMIN" may not be reproducible.
ERROR: Schema "ADMIN" contains a failed migration to version 20260101000006 !
flyway repair output:
Successfully repaired schema history table "ADMIN"."flyway_data_migrations" (execution time 00:01.3s).
Manual cleanup of the remaining effects of the failed migration may still be required.
--------------------------------------------------------------------
QUESTION
--------------------------------------------------------------------
Is there any OFFICIAL, supported Flyway mechanism (OSS or Teams) to
avoid the "contains a failed migration" block for a genuine DML-only
migration failure on Oracle, equivalent to how PostgreSQL's
transactional DDL support avoids ever writing a success=0 row in
the first place? We are not running any DDL in our Oracle
migrations — only DML wrapped in PL/SQL blocks with an application-
level row-count check that raises an error on mismatch.