复杂分支系统中的数据库迁移

Chr*_*isR 31 git database-migration database-versioning git-branch

在我们当前的开发工作流程中,我们引入了数据库迁移(使用Ruckusing)以使我们的开发人员的db模式保持同步.它工作得很好,使用起来非常简单,但现在我们已经切换到git作为VCS,我们正面临着数据库版本控制系统中的下一个问题.

在检查已经处于开发状态一段时间的分支时,可能会发生数据库模式与我来自的分支中的模式分歧很多.这在某些情况下会导致数据库冲突.从逻辑上看,似乎我们需要根据我们以前的分支运行迁移,但这可能会非常快速地复杂化,并且肯定会遇到一些问题.据我所知,没有一个分支感知的数据库迁移系统?

当切换到功能分支时增加了复杂性我们可能需要运行一些迁移而其他功能下降...技术上这似乎不可能使用我们当前的dbmigration脚本,是否有任何理智的替代方案?在非常活跃和分支的开发系统中是否有任何首选的数据库迁移方法?

Kai*_*nen 28

我不同意增量迁移被腐烂.在我看来,拥有一套自己开发的脚本比使用真正的工具来实现这样的工作会更容易跟踪这些更改.我以前必须自己处理类似的情况,所以希望我可以分享一些见解.

根据我的经验,RDBMS模式和分支不能很好地混合.根据您的分支,模式应该至少有些相似,在这种情况下,迁移不应该有太大差异.或者我可能只是误解了问题的全部范围.如果你试图将客户特定的代码保存在分支上,那么也许你应该考虑一种模块化的方法.我们做了类似的事情,有规则说客户特定的架构发生了变化,代码只能依赖于公共代码库,而不是相反.我们还根据模块和日期设置模块更改集之间的优先级,因此我们对大多数部分了解更改的应用顺序.当然,YMMV,但在不知道您当前的设置的情况下很难给出细节.

在我的旧公司,我们成功使用了一种名为Liquibase的工具,听起来与您使用的工具类似.基本上它是一个用于获取数据库模式的工具,以及从一个已知状态到另一个已知状态的所有数据.同一个变更集只应用一次,因为liquibase维护一个带校验和的更改日志.更改日志以特定的XML格式编写.如果您需要其他选择,我强烈建议您尝试一下.

无论如何,我们处理客户代码和分支的方式是为给定的分支设置特定的DB /模式.这样,您可以从分支点获取架构和数据,并仅将diff迁移到当前情况.我们没有撤消变化,即使理论上的liquibase可以支持这一点,因为我们认为它太麻烦且容易出错.鉴于liquibase保持自己的状态,迁移总是像在给定分支上获取当前状态一样容易,并且应用全部.仅应用了新的更改集,使架构处于良好状态.

我们使用mercurial,它像git一样分发,因此设置非常相似.我们还在开发笔记本电脑上设置了开发人员特定的本地数据库,以及针对不同客户和阶段(开发,集成,生产)的许多环境,因此该模型进行了真正的测试,并且效果出奇的好.我们在变更集中遇到了一些冲突,但我们大多能够在问题出现后很快解决这些冲突.本地开发环境实际上是最困难的部分,因为在开发过程中可能会引入一些模式更改,这些更改并不总是与以后的更改集兼容,而是更改的结构化特性,并且具有已知状态可以恢复为极少数真正的问题.

这种方法有一些注意事项:

  1. 必须在更改集中实现对架构的所有更改和任何更改.困惑的最大原因总是有人只是摆弄了一下.
  2. 第一点也适用,即使您使用的是修改架构的工具,例如像Hibernate这样的ORM工具.你需要与这个工具非常亲密,以了解它所做的和需要的变化.
  3. 所有用户都必须购买,并接受教育遵守规则.检查1.
  4. 迁移大量变更集开始花费太多时间.此时你需要创建一个新的基线,这可能有点棘手,特别是有很多分支.提前做好计划也是好事,至少知道所有现有的DB分支.
  5. 您需要提前计划分支,以了解它们是否会在某些时候迁移回master.朴素合并可能不适用于架构更改.
  6. 对于寿命很长的分支和分离的数据集,此模型可能不够强大

但重点是,您对数据库的结构和控制越多,迁移就越容易.因此,Liquibase等工具可以成为帮助您跟踪这些变化的宝贵资产.这比更简单的模型更适用于更复杂的模型,所以请至少不要考虑转储已有的所有工具.并花些时间探索其他替代工具.

一些结构和控制总比没有好,甚至更糟,认为你掌握了大量的手动脚本.

  • 我不确定为什么你认为有大量的脚本无法控制.如果您的团队编写并维护这些脚本,那么您就完全可以*控制.您不相信某些第三方工具可以正确解决复杂问题,而是直接负责所做的工作. (2认同)

Tom*_*son 15

我认为增量迁移的整个想法非常糟糕,真的.在像你这样的复杂环境中,它确实不起作用.你可以让它适用于简单的分支模式,但对于任何复杂的事情,它将是一场噩梦.

我现在使用的系统采用了不同的方法:我们无法进行增量迁移,只能从基线重建数据库.在初始开发期间,该基线是一个空数据库,在维护期间,它是实时数据库的副本(从转储中恢复).我们只有一堆SQL和XML脚本,我们应用于基线以获得当前系统(本质上是迁移,但不是设计为以递增方式运行).更新或切换分支非常简单:核对数据库,加载转储以建立基线,运行脚本.

这个过程不像运行一些迁移那么快,但它足够快.你需要花很长的时间才能去喝杯咖啡,但是吃的时间不够长.

最大的优势在于,从数据库开始,这意味着该过程完全独立于历史,因此不需要知道或关心跨越分支,回溯过去或其他任何事情.

当您发布实时版本时,您显然会做一些不同的事情:您不会对数据库进行核对或加载转储,因为系统已经处于基线状态(基线被定义为实时系统的状态!).你只需运行脚本.然后,进行新的转储以用作开发的新基准.

  • 如何针对数据库运行"一堆SQL和XML脚本"与增量迁移不同?你的意思是脚本不依赖于彼此吗?它听起来与增量迁移系统基本相同(从基线开始,按顺序应用脚本). (8认同)
  • 这是我们的突破性发现,我将以低廉的价格与您分享.实际上,我不知道这种方法在我公司之外是否普遍存在(实际上,它在我公司内部甚至不是普遍的!).这不是我在讨论迁移等时遇到的问题.实际上,这对于[程序员](http://programmers.stackexchange.com/)来说是一个很好的问题. (2认同)