【问题标题】:Iterative database migration in with git/gerrit使用 git/gerrit 进行迭代数据库迁移
【发布时间】:2012-12-29 15:15:39
【问题描述】:

问题:如何处理提交缓慢/gerrit 的顺序数据库迁移脚本。

设置如下:

  • 数据库表的持续开发是通过添加具有顺序名称(12.sql、13.sql、14.sql 等)的文件来完成的
  • 在数据库中设置了版本号
  • 迁移工具会根据文件检查版本,以查看是否存在未处理的数据库迁移

这种方法的主要问题(在其他情况下效果很好)是,当两个开发人员同时添加迁移脚本时,他们中最后一个提交的人会遇到合并冲突。在 subversion 中(我们一直使用到现在),这是一个树冲突,提交者通过还原该文件并使用新文件名添加它来处理,作为最后一个操作。由于我们在主干上使用了这些东西,他们通常会设法修复文件名作为最后的快速操作。

现在我们正在迁移到 git,冲突将改为在文件中显示为差异,这使得分离两个提交的文件(它们可能是不同提交包的一部分,以及其他文件)变得更加棘手。此外,由于我们使用 gerrit 进行代码审查,在将文件推送到主 git 存储库之间会有延迟,因此时不时会出现这种情况:

  1. 您推送迁移
  2. Gerrit 在代码审查后发生冲突
  3. 您通过重命名文件来解决冲突,然后推送新的提交(必须重新审核)
  4. 有人在代码审查之前设法进行了新迁移,因此 Gerrit 再次发生冲突
  5. 您通过重命名文件来解决冲突,然后推送新的提交(必须重新审核)
  6. 从 4 开始重复,直到您幸运并且 Gerrit 成功提交迁移。

解决这种情况的最佳方法是什么?

【问题讨论】:

    标签: database git migration gerrit


    【解决方案1】:

    我使用liquibase 来管理我的数据库迁移。

    它使用 XML 语法来描述数据库的每个“变更集”。虽然这可能会成为采用的障碍,但我发现它将来自不同开发人员的贡献合并到同一个文件中变得更加容易。

    <changeSet id="bob-20130115-1" author="bob">
        <createTable tableName="commontable">
           ..
           ..
        </createTable>
    </changeSet>
    
    <changeSet id="tom-20130115-1" author="tom">
        <addColumn tableName="commontable">
            <column name="newcolumn" type="varchar(255)"/>
        </addColumn>
    </changeSet>
    

    使用 liquibase 的第二个优点是它支持回滚。如果发生冲突,我们可以撤消变更集,将我们带回上一个稳定版本,修复迁移文件并执行全新更新。

    如果您没有切换工具的便利,那么我建议您也许采用 liquibase 的方法,将 DEV 期间的每次迁移都视为“变更集”。每次迭代使用单个迁移文件,并在每个开发人员贡献的开始和结束处添加注释。在合并冲突的情况下,不要尝试重新编写 SQL,而是重新排序,以便一个开发人员的更改在其他人之前或之后。 (强制其他开发人员创建另一个文件的方法是有效的,但我发现在实践中很难实现,当第三个开发人员稍后出现并与序列中的下一个数字冲突时......)

    在没有回滚功能的情况下管理集成环境很棘手......除了每次都从头开始重建数据库之外,我不知道任何简单的方法。也许唯一有效的方法是听从 VonC 的建议,将数据库更改者的数量保持在最低限度。

    注意事项:

    • 每个使用自己的数据库的开发人员都是一个给定的。您正在使用迁移工具,因此应该没有异议。它简化了问题,尤其是当您需要消除和重建架构时。它还迫使您解决“测试数据”挑战....当我在一个测试数据位于单个数据库实例中的项目上工作时磨砺我的齿轮....
    • 我最近发现SQL Alchemy migrate 具有与liquibase 相同的回滚功能。它强制您为每次迁移编写前滚和回滚脚本。

    【讨论】:

    • Liquibase(和方法)看起来很有趣。我将不得不等待,看看是否会发生这样的生活方式改变。我想知道 git 将如何处理两个开发人员添加到这样的 xml 文件末尾 - 解决冲突可能多么容易/棘手。
    • @TV'sFrank 添加到文件末尾的更改很容易合并,对文件末尾的冲突更改很棘手... Liquibase 更改作为更改集块添加,这确实很有帮助。如果冲突真的很混乱,我只需查看每个文件,然后按顺序添加两个变更集。如果您面临合并原始 SQL 的痛苦,我建议您尝试这样做。将每个开发人员更改视为一个更改块。
    【解决方案2】:

    我将 Liquibase 作为一种解决方案。恕我直言,马克·奥康纳(Mark O'Connor)没有很好地指出 Liquibase 的一个属性是,Liquibase 维护了应用变更集的 列表最后 在您的方法中应用的变更.

    因此(只要更改标识符不冲突)分支不是问题。 Liquibase 简单地应用所有尚未在 XML 中按顺序应用的未完成的变更集。作为检测冲突的功能,Liquibase 还存储了变更集源代码本身的 MD5 哈希,因此它也能够检测到变更“XY”本身的内容已更改。在这种情况下,您必须手动找出问题所在,并教导您的开发人员同事在任何第三方应用后不要更改任何变更集。

    如果您不想切换/引入新的数据库版本控制工具,例如 liquibase,我认为您可以轻松地将您的自定义方法扩展到这个方向。只需维护已应用更改的列表,只要您的文件名不匹配,您就可以很好地处理分支。

    【讨论】:

      【解决方案3】:

      两个开发者同时添加一个迁移脚本

      他们需要在自己的分支上进行修改,并触发对 Gerrit 的单独审核。
      一位集成商(或两位开发人员中的一位)将负责合并和审查这两项开发工作。

      那,或者两者之间的通信需要改进,如果“dev 1”需要获得一些补丁(代表“dev 2” "的工作) 首先在 "dev 1" 的工作树中。

      【讨论】:

        猜你喜欢
        • 2017-02-10
        • 2019-12-02
        • 1970-01-01
        • 2020-04-21
        • 1970-01-01
        • 1970-01-01
        • 2018-11-26
        • 2016-05-06
        • 2016-10-15
        相关资源
        最近更新 更多