【发布时间】: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.groovy 和changelog-1.0.groovy。我将changelog-1.0.groovy称为changelog #1
3.) 我现在尝试使用刚刚创建的变更日志来初始化我的生产数据库。我在我的配置中设置了数据库迁移updateOnStart 和updateOnStartFileNames,如我链接到的教程中所示。我的生产数据库存在,但为空(没有表)。我的生产环境的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 遗漏或无法执行的操作,也可以简单地清理更改以使它们不那么冗长。