我怎样才能把数据库下git(版本控制)?

我正在做一个web应用程序,我需要做一些重大更改的分支,这些更改需要更改数据库模式,所以我想把整个数据库都放在git下。

我怎么做? 有一个特定的文件夹,我可以保持在一个Git仓库? 我怎么知道哪一个? 我怎样才能确定我把正确的文件夹?

我需要确定,因为这些变化不是向后兼容的; 我不能搞砸了。

我的例子中的数据库是PostgreSQL

编辑:

有人build议采取备份,并将备份文件放在版本控制下,而不是数据库。 说实话,我发现真的很难下咽。

一定有更好的方法。

更新:

好,那么没有更好的办法,但是我还是不太确定,所以我会改变这个问题:

我想把整个数据库放在版本控制之下,我可以使用什么数据库引擎,这样我就可以将实际的数据库放在版本控制下,而不是转储了?

sqlite会是友好的?

由于这只是开发环境,我可以select任何我想要的数据库。

EDIT2:

我真正想要的不是追踪我的发展历史,而是能够从我的“新的激进变化”分支切换到“当前稳定的分支”,并能够例如修复一些错误/问题等等,与当前稳定的分支。 这样,当我切换分支,数据库自动变成与我目前的分支兼容。 我并不十分关心实际的数据。

取一个数据库转储和版本控制。 这样它是一个平面文本文件。

我个人build议你同时保存数据转储和模式转储。 通过这种方式使用diff,可以非常容易地看到模式中从修订版本到修订版本发生了什么变化。

如果你做了很大的改变,你应该有一个辅助数据库,让你对新模式进行修改,而不会碰到旧数据库,就像你说你正在创build一个分支一样。

查看重构数据库( http://databaserefactoring.com/ ),了解一些用于维护数据库并改变代码的好技巧。

只要说你问的是错误的问题。 不要把你的数据库放到git中,你应该把你的改变分解成小的可validation的步骤,这样你就可以轻松地迁移/回滚模式更改。

如果你想有完整的可恢复性,你应该考虑归档你的postgres WAL日志,并使用PITR(时间点恢复)来回放/转发交易到特定的已知良好状态。

我开始想到一个非常简单的解决scheme,不知道为什么我没有想到它之前!

  • 复制数据库(架构和数据)。
  • 在新主要更改的分支中,只需将项目configuration更改为使用新的重复数据库即可。

这样我可以切换分支而不用担心数据库模式的变化。

编辑:

重复,我的意思是创build另一个名称不同的数据库(如my_db_2 ); 不做转储或类似的东西。

而不是手动转储数据库并将其保存到git中,请使用Offscale DataGrove 。

DataGrove基本上是一个数据库版本控制 – 它跟踪整个数据库(架构和数据)的变化,并允许您将版本标记到其存储库中。 你可以把它和git一起使用,并且每次签入代码时都会标记一个版本,每当你提取代码的时候就加载正确的DB状态。

特别是关于“编辑2” – 与DataGrove你可以简单地有两个分支的DB,一个为你的每个代码分支。 加载代码的某个分支时,DataGrove将自动重新创build整个数据库状态,其中包含该版本/分支的所有数据。 这意味着你可以用一个简单的命令在开发分支之间切换。

使用像LiquiBase这样的东西可以让你保持你的Liquibase文件的版本控制。 你只能标记生产的变化,并保持你的数据库最新的生产或发展,(或任何你想要的scheme)。

有一个名为Klonio的重大开发工具,其Beta版本可供使用。 它现在支持MongoDB和MySQL。

当然,它有git集成,你可以单独快照你的模式,甚至包括数据。

在这个目的下build立了一个名为Migrations的伟大项目。

它仍然在alpha状态,并build立了PHP。

http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/index.html

看看RedGate SQL源代码pipe理。

http://www.red-gate.com/products/sql-development/sql-source-control/

此工具是一个SQL Server Management Studiopipe理单元,它允许您将数据库放置在使用Git的源代码pipe理下。

这个价格有点贵,每个用户495美元,但有28天免费试用。

注意我不以任何方式隶属于RedGate。

你不能没有primefaces性,没有使用pg_dump或快照文件系统就不能获得primefaces性。

我的postgres实例在zfs上,我偶尔会快照。 这大概是即时和一致的。

你想要的精神,或许就像Post Facto ,它将数据库的版本存储在数据库中。 检查此演示文稿 。

这个项目显然从来没有真正去过,所以它可能不会马上帮你,但这是一个有趣的概念。 我担心这样做会很困难,因为即使是第一版,为了让人们相信他们的工作,也必须把所有的细节都弄清楚。

我碰到过这个问题,因为我有类似的问题,在那里接近一个基于DB的目录结构,存储'文件',我需要Git来pipe理它。 它通过一个云分布,使用复制,因此它的访问点将通过MySQL。

上述答案的要点似乎同样提出了一个解决问题的替代scheme,哪种方法没有考虑到使用Git来pipe理数据库中的某些东西的问题,所以我会试着回答这个问题。

Git是一个系统,它本质上存储一个数据库的增量(差异),可以重新组合,以便重现上下文。 git的正常用法假定上下文是一个文件系统,而那些deltas在这个文件系统中是diff,但是实际上所有的git都是deltas的分层数据库(分层的,因为在大多数情况下,每个delta是一个提交至less1父母,安排在一棵树)。

只要你能产生一个delta,理论上git可以存储它。 这个问题通常是git期待的上下文,它生成的增量为文件系统,同样,当你签出git层次结构中的一个点时,它希望生成一个文件系统。

如果你想pipe理变更,在一个数据库中,你有两个离散的问题,我会分开处理(如果我是你)。 第一个是模式,第二个是数据(尽pipe在你的问题中,你声明的数据不是你所关心的)。 我曾经遇到的一个问题是开发和产品数据库,在这个数据库中,开发人员可以对模式进行增量更改,而这些更改必须在CVS中logging下来,然后传播到现有数据库中,同时增加几个“静态”表。 我们通过一个名为Cruise的第三个数据库来做到这一点,它只包含静态数据。 Dev和Cruise的模式在任何时候都可以进行比较,我们有一个脚本来处理这两个文件的差异,并生成一个包含ALTER语句的SQL文件来应用它。 同样,新的数据可以被提炼成一个包含INSERT命令的SQL文件。 只要添加了字段和表,并且从不删除,进程就可以自动生成SQL语句来应用增量。

git生成deltas的机制是diff ,其中一个或多个deltas与一个文件结合的机制称为merge 。 如果你能想出一个从不同的上下文来区分和合并的方法,git应该可以工作,但正如已经讨论过的,你可能更喜欢一个为你做的工具。 我首先想到解决这个问题是这个https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#External-Merge-and-Diff-Tools详细说明如何取代git的内部差异和合并工具。 我会更新这个答案,因为我提出了一个更好的解决scheme,但在我的情况下,我希望只需要pipe理数据更改,因为基于数据库的文件存储可能会改变,所以我的解决scheme可能并不完全是你所需要的。

我认为X-Istence是正确的,但是你可以对这个策略进行一些改进。 首先使用:

 $pg_dump --schema ... 

转储表,序列等,并将这个文件放在版本控制下。 您将使用它来分隔您的分支之间的兼容性更改。

接下来,为包含您的应用程序运行所需configuration的表集执行数据转储(应该可能跳过用户数据等),如表单默认值和其他数据非用户可修改的数据。 您可以select性地使用以下方法:

 $pg_dump --table=.. <or> --exclude-table=.. 

这是一个好主意,因为当你的数据库达到100Mb +时,回购可能变得非常笨重,当做一个完整的数据转储。 更好的办法是备份testing应用程序所需的更less量的数据。 如果您的默认数据非常大,但这仍然可能会导致问题。

如果您确实需要在回购站中放置完整备份,请考虑在源树之外的分支中进行。 一个外部备份系统有一些参考匹配的SVN rev可能是最好的,但这。

此外,我build议使用文本格式转储为二进制修订目的(至less为模式),因为这些更容易区分。 您可以随时在签入前压缩这些空间以节省空间。

最后,如果还没有,请查看postgres备份文档 。 您对备份“数据库”而不是转储进行评论的方式让我怀疑是否在考虑基于文件系统的备份(有关注意事项,请参见第23.2节)。

这个问题已经得到了很好的回答,但是我想用一个小小的build议来补充X-Istence和Dana Sane的回答。

如果您需要某种程度的粒度的版本控制,比如每天说一次,您可以将两个表和模式的文本转储与rdiff-backup这样的工具结合起来进行增量备份。 这样做的好处是,不用存储每日备份的快照,只需存储与前一天的差异即可。

有了这个,你既具有版本控制的优势,又不会浪费太多的空间。

无论如何,直接在大的平面文件上直接使用git并不是一个好的解决scheme。 如果你的数据库变得太大,git会开始pipe理文件时遇到一些问题。

我会build议neXtep控制数据库的版本,它有一个很好的文档和论坛,解释如何安装和遇到的错误。 我已经testing了它的PostgreSQL的9.1和9.3,我能够得到它为9.1的工作,但对于9.3它似乎并没有工作。

我在我的个人项目中做的是,我将整个数据库存储到Dropbox,然后指向MAMP,WAMP工作stream程,以便从那里使用它。这样,数据库始终是最新的,我需要做一些开发。 但是这只是开发! 生活网站正在使用自己的服务器,当然! 🙂

在git版本控制下存储每个级别的数据库更改就像每次提交时都推送整个数据库,并在每次提交时恢复整个数据库。 如果你的数据库很容易发生关键的变化,你不能松动它们,你可以更新你的pre_commitpost_merge钩子。 我对我的一个项目也做了同样的事情,你可以在这里find方向。

我就是这么做的:

由于您有关于数据库types的免费select,请使用基于文件的数据库,例如firebird。

创build一个模板DB,其模式适合您的实际分支并将其存储在您的存储库中。

以编程方式执行应用程序时,创build模板数据库的副本,将其存储在其他位置,然后使用该副本。

这样,您可以将数据库架构置于版本控制之下而不需要数据。 如果你改变你的模式,你只需要改变模板DB

我们曾经在一个标准的LAMPconfiguration上运行一个社交网站。 我们有一个Live服务器,testing服务器,开发服务器,以及本地开发人员机器。 所有都使用GIT进行pipe理。

在每台机器上,我们都有PHP文件,还有MySQL服务,还有一个用户可以上传图片的文件夹。 Live服务器增长到100K(!)经常性用户,转储大约2GB(!),Image文件夹大约50GB(!)。 当我离开的时候,我们的服务器已经达到了它的CPU,Ram的极限,最重要的是,并发的networking连接限制(我们甚至编译了我们自己版本的网卡驱动程序来最大化服务器'lol')。 我们不能( 也不应该假设您的网站 )在GIT中放置了2GB的数据和50GB的图片。

要轻松pipe理GIT下的所有内容,我们将通过将这些文件夹path插入.gitignore来忽略二进制文件夹(包含图像的文件夹)。 我们还在Apache documentrootpath之外有一个名为SQL的文件夹。 在那个SQL文件夹中,我们会把来自开发者的SQL文件放在增量编号(001.florianm.sql,001.johns.sql,002.florianm.sql等)中。 这些SQL文件也由GITpipe理。 第一个sql文件确实会包含一大组数据库模式。 我们不会在GIT中添加用户数据(例如用户表的logging或注释表),但是像config或拓扑或其他站点特定数据的数据在sql文件(也就是GIT)中保存。 大多数情况下,它的开发人员(谁知道最好的代码),确定什么,什么不是由GIT维护的SQL模式和数据。

当到达发行版时,pipe理员login到dev服务器,将live分支与所有开发人员合并,并将开发计算机上需要的分支合并到更新分支,并将其推送到testing服务器。 在testing服务器上,他检查Live服务器的更新过程是否仍然有效,并且快速连续地将Apache中的所有stream量指向占位符站点,创build一个数据库转储,将工作目录从“活动”指向“更新',将所有新的sql文件执行到mysql,并将stream量重新指定回正确的站点。 当所有利益相关者在审查testing服务器后都同意时,pipe理员从testing服务器到Live服务器做了同样的事情。 之后,他将生产服务器上的活动分支合并到所有服务器的主分支,并重新分配所有活动分支。 开发商自己负责重新devise分支机构,但他们一般都知道自己在做什么。

如果testing服务器上有问题,例如。 合并有太多的冲突,然后代码恢复(指向工作分支回到“活”),并从未执行的SQL文件。 sql文件执行的那一刻,被认为是一个不可逆的行为。 如果SQL文件不能正常工作,那么使用Dump恢复数据库(开发人员告诉他们,因为提供了不合格的SQL文件)。

今天,我们同时维护一个sql-up和sql-down文件夹,使用相同的文件名,开发人员必须testing这两个升级的sql文件可以同样降级。 这最终可以用bash脚本来执行,但是如果人类继续监视升级过程,这是一个好主意。

这不是很好,但它的可pipe理性。 希望这可以让我们深入了解一个真实,实用,相对高可用性的站点。 不pipe有点过时,但仍然遵循。

我想做类似的东西,把我的数据库更改添加到我的版本控制系统。

我将遵循弗拉基米尔·霍里科夫(Vladimir Khorikov)的“数据库版本化最佳实践”这篇文章中的想法。 总之我会的

  • 将其模式和参考数据存储在源控制系统中。
  • 对于每一个修改,我们将创build一个单独的SQL脚本的变化

万一它有帮助!

使用像iBatis Migrations( 手动 , 简短video教程 )这样的工具,它允许您在项目的整个生命周期中对数据库进行版本控制,而不是数据库本身。

这使您可以select性地将各个更改应用于不同的环境,保留更改日志,以便在哪些环境中进行更改,创build脚本以应用更改A到N,回滚更改等。

我想把整个数据库放在版本控制之下,我可以使用什么数据库引擎,这样我就可以将实际的数据库放在版本控制下,而不是转储了?

这不是数据库引擎的依赖。 通过Microsoft SQL Server有很多版本控制程序。 我不认为这个问题可以用git来解决,你必须使用一个特定于pgsql的schema版本控制系统。 我不知道这样的事情是否存在

这是我在我的项目中要做的事情:

  • 单独的数据和模式和默认数据。

数据库configuration存储在不受版本控制(.gitignore)的configuration文件中

数据库默认值(用于设置新项目)是一个在版本控制下的简单SQL文件。

对于数据库模式,在版本控制下创build数据库模式转储。

最常见的方法是拥有包含SQL语句的更新脚本(ALTER Table ..或UPDATE)。 您还需要在数据库中保存当前版本模式的位置)

看看其他大的开源数据库项目(piwik,或者你最喜欢的cms系统),它们都使用更新logging(1.sql,2.sql,3.sh,4.php.5.sql)

但是,这是一项非常耗时的工作,您必须创build并testing更新脚本,并且需要运行通用的更新脚本来比较版本并运行所有必要的更新脚本。

所以理论上(这就是我所期待的)你可以在每次更改之后抛弃数据库模式(手动,结合,git钩子(也许在提交之前))(并且只在一些非常特殊的情况下创build更新logging)

之后,在您的通用更新(运行正常更新logging,特殊情况下),然后比较模式(转储和当前数据库),然后自动生成nessesary ALTER语句。 有一些工具可以做到这一点,但还没有find一个好的。

我已经发布了一个sqlite的工具,它可以满足你的要求。 它使用一个自定义的比较驱动程序,利用sqlite项目工具'sqldiff',UUIDs作为主键,并离开sqlite rowid。 它仍然在alpha,所以反馈是赞赏。

Postgres和mysql更棘手,因为二进制数据保存在多个文件中,如果能够快照,它甚至可能不是有效的。

https://github.com/cannadayr/git-sqlite