Search code examples
grailstransactionsgrails-orm

Grails dbm-update & change_log changesets: transactional or not?


I was under the impression that changesets within migration scripts were transactional, but I am seeing that in practice they are not.

For the simplest example of this, create a basic changeset entry, maybe as follows:

changeSet(author: "some_email@server.com", id: "1-1", description: "An example changeset for a changelog.groovy.") {
    createTable(tableName: "table_name") {
        column(autoIncrement: "true", name: "id", type: "BIGINT") {
            constraints(nullable: "false", primaryKey: "true")
        }

        column(name: "version", type: "BIGINT") {
            constraints(nullable: "false")
        }

        column(name: "name", type: "VARCHAR(64)") {
            constraints(nullable: "false")
        }

        column(name: "name", type: "VARCHAR(64)") {
            constraints(nullable: "false")
        }

    }

}

Now, obviously we cannot add two columns of the same name, so this should fail - and rollback. But it doesn't rollback. The table is created and the first column is added - despite the fact it is a "bad" changeset.

So, the questions are -

1) are changelog.groovy changesets transactions?

2) is grails dmb-update supposed to execute changesets transactionally?

3) if so, what did we configure incorrectly?


Solution

  • Database migrations in Grails are not transactional. If you need the ability to rollback a failed changeset you have to write the rollback yourself.

    As Burt points out "The primary issue is that transactions, rollback, etc. are primarily a data/DML concept. Some databases have at least partial support for rolling back structural/DDL changes, but it's very impractical in the general case".