15

我已经开始与一个小型开发团队一起使用 git,这些开发团队来来去去从事不同的项目;在我们开始使用 Wordpress 之前,它运行良好。因为 Wordpress 在 MySQL 中存储了很多配置,所以我们决定需要将其包含在我们的提交中。

这工作得很好(在预提交时使用 msyql 转储,并在签出后将转储文件推送到 mysql 中),直到两个人对插件进行修改并提交,然后一切都再次崩溃。

我查看了我能找到的所有解决方案,并认为 Liquibase 是最接近的选择,但对我们不起作用。它要求您在 XML 中指定模式,这实际上是不可能的,因为我们使用的插件会自动将数据/表/修改插入数据库。
我计划在几天内悬赏它,看看是否有人有“金发姑娘的解决方案”:

问题:
有没有办法在语义上对 MySQL 数据库进行版本控制(不使用差异编辑:这意味着它不只是采用两个版本并对其进行差异化,而是记录按顺序运行的实际查询以从旧版本中获取到当前的)不需要开发人员编写的模式文件,并且可以使用 git 合并。

我知道我不可能是唯一一个遇到这种问题的人,但希望有人能解决这个问题吗?

4

1 回答 1

4

处理数据库版本控制的正确方法是通过仅添加的版本脚本。由于这种性质,它会一直发生冲突,因为每个分支都将附加到同一个文件中。你想要那个。它使开发人员意识到彼此的更改如何影响其数据的持久性。Rerere 将确保您只解决一次冲突。(请参阅我关于重新共享的博客文章:http: //dymitruk.com/blog/2012/02/05/branch-per-feature/

将每个更改都包含在 if then 子句中,该子句检查版本号、更改架构或修改查找数据或其他内容,然后递增版本号。您只需为每次更改继续执行此操作。

在伪代码中,这是一个示例。

if version table doesn't exist
  create version table with 1 column called "version"
  insert the a row with the value 0 for version
end if
-- now someone adds a feature that adds a members table
if version in version table is 0
  create table members with columns id, userid, passwordhash, salt
    with non-clustered index on the userid and pk on id
  update version to 1
end if
-- now some one adds a customers table
if version in version table is 1
  create table customers with columns id, fullname, address, phone
    with non-clustered index on fullname and phone and pk on id
  update version to 2
end if
-- and so on

这样做的好处是,如果您使用的是静态语言,您可以在成功构建测试项目后自动运行此脚本 - 它总是会让您保持最新状态。如果您刚刚更新到最新版本,则所有验收测试都应该通过。

问题是,你如何同时在 2 个不同的分支上工作?我过去所做的只是启动了一个新实例,该实例在 db 名称中由分支名称分隔。您的配置文件已被清理(参见 git smudge/clean)以将连接字符串设置为指向该分支的新实例或现有实例。

如果您使用的是 ORM,则可以自动生成此脚本,例如,nhibernate 将允许您将尚未反映在 db 模式中的图形更改导出为 sql 脚本。因此,如果您为客户类添加了映射,NHibernate 将允许您生成表创建脚本。您只需编写添加 if-then 包装器的脚本,即可在功能分支上实现自动化。

集成分支和发布候选分支有一些特殊要求,如果您要重置这些分支,则需要擦除和重新创建数据库。通过确保新版本git branch --contains是旧版本,这很容易做到。如果没有,请擦拭并再生。

我希望这很清楚。这在过去运作良好,并且要求每个开发人员能够在他们的机器上创建和销毁他们自己的数据库实例,尽管可以在具有额外实例命名约定的中央实例上工作。

于 2012-07-17T07:52:56.737 回答