【问题标题】:Grails database migration changelog woesGrails 数据库迁移变更日志问题
【发布时间】:2012-07-10 14:33:16
【问题描述】:

我正在努力学习 this 教程。以下是我采取的步骤:

1.)我首先创建我的空变更日志。在我运行这个命令之前,我将我的开发 dbCreate 设置为 create

grails dbm-create-changelog

2.) 然后我生成初始的 gorm 变更日志。教程说我应该使用prod 标志,但由于我的生产数据库是空的,所以我放弃了prod 标志。在运行此命令之前,我将我的开发 dbCreate 设置注释掉。

grails dbm-generate-gorm-changelog --add changelog-1.0.groovy

此时我的migrations 文件夹包含文件changelog.groovychangelog-1.0.groovy。我将changelog-1.0.groovy称为changelog #1

3.) 我现在尝试使用刚刚创建的变更日志来初始化我的生产数据库。我在我的配置中设置了数据库迁移updateOnStartupdateOnStartFileNames,如我链接到的教程中所示。我的生产数据库存在,但为空(没有表)。我的生产环境的dbCreate 设置已被注释掉。

grails prod run-app

问题:

乍一看这似乎有效,但是当我运行grails prod dbm-gorm-diff 并生成changelog #2 时,我看到了不应该存在的更改。与生产数据库的当前状态相比,我还可以看到变更集是合法的。这意味着生产数据库没有使用changelog #1 正确初始化。不应该存在任何更改,因为我什么也没做。我在运行grails prod run-app 后立即运行grails prod dbm-gorm-diff

changelog #2 中有五个变更集。我已经验证所有这些变更集都在changelog #1 中表示。 changelog #2 中的前四个变更集都有 unique: "true"。这四个变更集也是在changelog #1 中包含unique: "true" 的唯一变更集。我仍然无法解释为什么存在第五个变更集。我看不出它没有什么特别之处,尽管它是用于Spring Security plugin 使用的user_role 表。这里是changelog #2

databaseChangeLog = {

    changeSet(author: "typoknig (generated)", id: "1341970550063-1") {
        createIndex(indexName: "authority_unique_1341970549765", tableName: "role", unique: "true") { // This table is for the Spring Security plugin's "Role" domain class.
            column(name: "authority")
        }
    }

    changeSet(author: "typoknig (generated)", id: "1341970550063-2") {
        createIndex(indexName: "name_unique_1341970549772", tableName: "foo", unique: "true") { // This is just a table for one of my domain classes that happens to have a field with a unique constraint.
            column(name: "path")
        }
    }

    changeSet(author: "typoknig (generated)", id: "1341970550063-3") {
        createIndex(indexName: "name_unique_1341970549774", tableName: "bar", unique: "true") { // This is just a table for one of my domain classes that happens to have a field with a unique constraint.
            column(name: "name")
        }
    }

    changeSet(author: "typoknig (generated)", id: "1341970550063-4") {
        createIndex(indexName: "username_unique_1341970549777", tableName: "user", unique: "true") { // This table is for the Spring Security plugin's "User" domain class.
            column(name: "username")
        }
    }

    changeSet(author: "typoknig (generated)", id: "1341970550063-5") {
        createIndex(indexName: "FK143BF46A5FBC0B79", tableName: "user_role") { // This table is for the Spring Security plugin's "UserRole" domain class.
            column(name: "role_id")
        }
    }
}

我需要做些什么来确保我的生产数据库已正确初始化?

更新 #1:

我不知道为什么,但 createIndex 不能与 unique: "true" 合作。对于前四个变更集,我只是将unique: "true" 移动到最初在changeset #1 中创建相关列的位置。这仅留下changelog #2 中的第五个变更集需要处理。我仍然没有看到变更集有任何问题,所以我不明白为什么它没有被应用。

更新 #2:

我发现我可以将所有对createIndex 的调用从单个变更集中移到创建表(索引所属的)的相应变更集中。 这似乎解决了我所有的问题。 除非有人能提供令人信服的理由不这样做,否则我认为我会将这部分作为我的变更日志生成工作流程的一部分。例如这些变更集:

changeSet(author: "typoknig (generated)", id: "1342037835503-31") {
    createTable(tableName: "user_role") {
        column(name: "role_id", type: "bigint") {
            constraints(nullable: "false")
        }

        column(name: "user_id", type: "bigint") {
            constraints(nullable: "false")
        }
    }
}

changeSet(author: "typoknig (generated)", id: "1342037835503-103") {
    createIndex(indexName: "FK143BF46A4E6CF59", tableName: "user_role") {
        column(name: "user_id")
    }
}

changeSet(author: "typoknig (generated)", id: "1342037835503-104") {
    createIndex(indexName: "FK143BF46A5FBC0B79", tableName: "user_role") {
        column(name: "role_id")
    }
}

会是这个变更集:

changeSet(author: "typoknig (generated)", id: "1342037835503-31") {
    createTable(tableName: "user_role") {
        column(name: "role_id", type: "bigint") {
            constraints(nullable: "false")
        }

        column(name: "user_id", type: "bigint") {
            constraints(nullable: "false")
        }
    }
    createIndex(indexName: "FK143BF46A5FBC0B79", tableName: "user_role") {
        column(name: "role_id")
    }
    createIndex(indexName: "FK143BF46A4E6CF59", tableName: "user_role") {
        column(name: "user_id")
    }
}

【问题讨论】:

  • 您是否尝试过不依赖updateOnStart 功能,而是直接运行更新脚本?
  • 在运行 diff 时,您几乎总是会得到更改。 Diff 是不完美的,它应该被用作一个建议。当我做差异时,我总是得到 createIndex changeSets。我只是删除它们并保留/调整我需要的东西。
  • @Gregg 如果 diff 向我展示了已经应用于我的数据库的更改,我会很生气,但并不担心。但事实并非如此。差异是准确的,因为 changelog #1 未正确应用于我的生产数据库。生产数据库是从开发数据库创建的变更日志中初始化的,因此即使存在“差异”,数据库也应该是相同的。同样,情况并非如此。例如,关于changelog #2 中的第一个变更集,开发数据库在role 表中的authority 列上有unique 约束,而生产数据库没有。
  • @cdeszaq 我还没有尝试过。我会试一试并报告。
  • @Gregg - 这正是我所做的。既可以通过内置操作捕获 diff 遗漏或无法执行的操作,也可以简单地清理更改以使它们不那么冗长。

标签: grails database-migration


【解决方案1】:

变更集可以依赖于目标数据库。例如,用于将 MyISAM 表与 MySQL 和 dbm-gorm-diff 一起使用的 grails.org 站点总是会添加一些 createIndex 变更集,即使它们是在以前的变更集中定义的。

我真的不明白将 createIndex 声明移动到 createTable 变更集中会有什么不同。您能否说明这样做如何解决了您的所有问题?

【讨论】:

  • Peter,我看不出将 createIndex 声明移动到 createTable 变更集中会有什么不同,但确实如此。尽管我希望可以,但我无法解释它为什么起作用。
猜你喜欢
  • 2013-08-15
  • 2013-03-15
  • 2015-12-25
  • 2012-05-20
  • 2013-12-03
  • 2019-08-31
  • 2017-05-26
  • 2014-05-04
  • 2017-01-08
相关资源
最近更新 更多