FireDAC schema changes: wrap DDL in one transaction or go forward-only with compensating scripts?
0 reputation · 11 Sept 2020, 00:46 UTC
0 reputation · 11 Sept 2020, 00:46 UTC
I'm designing a schema migration strategy for a RAD Studio (Delphi) application that uses FireDAC against more than one target DBMS. The goal is a rollback-safe upgrade path when a schema change fails partway through.
Two documented approaches seem viable. First, wrap the DDL in an explicit transaction using TFDConnection.StartTransaction / Commit / Rollback, which works cleanly on Firebird and InterBase where DDL is transactional. Second, use forward-only migrations via TFDScript, pairing each change with a tested compensating script, which is the pattern recommended for DBMSs like Oracle or MySQL where DDL triggers an implicit commit and Rollback cannot undo it.
The tension: transactional DDL gives atomic rollback but only on DBMSs that support it, while forward-only scripts are portable but demand disciplined, tested compensating changes that can be destructive. I'm also unsure how much TxOptions and auto-commit settings affect whether my DDL actually runs inside the explicit transaction at all.
Should I standardize on one strategy across all targets, or branch per DBMS? How can I verify at runtime that a given DDL statement really executed inside my explicit transaction rather than auto-committing? Are there practical limits (e.g., schema locks on Firebird) that argue against long DDL transactions?
Branch per DBMS. Do not standardize on one strategy. Use transactional DDL with explicit TFDConnection.StartTransaction/Commit/Rollback on engines that support transactional DDL, and use forward-only migrations with tested compensating scripts on engines where DDL forces an implicit commit. Branching is the only rollback-safe way to cover Firebird/InterBase/PostgreSQL/SQL Server and Oracle/MySQL/SQLite in the same codebase.
FireDAC will execute DDL inside an explicit transaction when the driver and DBMS allow it. Whether Rollback actually undoes the DDL is a DBMS property, not a FireDAC property. Firebird and InterBase support transactional DDL. PostgreSQL and SQL Server support transactional DDL for most schema changes. Oracle and MySQL issue an implicit commit on many DDL statements, so Rollback cannot undo them. SQLite auto-commits DDL outside a transaction.
TFDConnection.AutoCommit controls whether FireDAC auto-commits each statement. For manual control set AutoCommit to False and use StartTransaction. TxOptions.AutoCommit and the driver-specific options affect this. TFDScript executes statements sequentially in the current transaction context when AutoCommit is False.
Long DDL transactions hold schema locks. On Firebird, a DDL transaction acquires exclusive locks on system tables and the affected objects, blocking concurrent DDL and sometimes DML until Commit/Rollback. For large tables or online systems, keep the transactional batch small and short.
Forward-only with compensating scripts is portable but requires idempotent, tested reverse scripts and careful ordering. Compensating scripts must be safe to run only after a known failure point.
To change the recommendation I need the exact DBMS and engine versions you must support. Which DBMS versions are in scope for this release?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.