如何在git(版本控制)下放置数据库?

时间:2009-05-11 03:49:32

标签: database git version-control postgresql

我正在做一个Web应用程序,我需要为一些重大更改创建一个分支,事实是,这些更改需要更改数据库模式,所以我想将整个数据库放在git下面

我该怎么做?是否有一个特定的文件夹,我可以保存在git存储库下?我怎么知道哪一个?我怎么能确定我正在放置正确的文件夹?

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

我的案例中的数据库是PostgreSQL

编辑:

有人建议进行备份并将备份文件置于版本控制下而不是数据库中。说实话,我发现真的很难吞下去。

必须有更好的方法。

更新

好的,所以没有更好的方法,但我仍然不太相信,所以我会稍微改变一下这个问题:

我想将整个数据库置于版本控制之下,我可以使用哪种数据库引擎,以便我可以将实际数据库置于版本控制下而不是转储?

sqlite会对git友好吗?

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

EDIT2:

我真正想要的不是跟踪我的开发历史,而是能够从我的“新激进变化”分支切换到“当前稳定分支”,并能够修复一些错误/问题等,与目前的稳定分支。这样,当我切换分支时,数据库自动神奇地变得与我当前所在的分支兼容。 我真的不太关心实际的数据。

25 个答案:

答案 0 :(得分:127)

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

我个人建议您同时保留数据转储和架构转储。这样使用diff就可以很容易地看到模式中从修订版本到修订版本的变化。

如果您要进行大的更改,您应该有一个辅助数据库,您可以将新架构更改为而不触及旧架构,因为正如您所说的那样,您正在建立分支。

答案 1 :(得分:48)

查看重构数据库(http://databaserefactoring.com/),了解一系列良好的技术,以便与代码更改一起维护数据库。

可以说你提出了错误的问题。您应该将更改分解为可验证的小步骤,而不是将数据库放入git,这样您就可以轻松地迁移/回滚模式更改。

如果您希望具有完全可恢复性,则应考虑存档postgres WAL日志并使用PITR(即时点恢复)将事务回放/转发到特定的已知良好状态。

答案 2 :(得分:26)

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

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

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

编辑:

副本,我的意思是创建另一个具有不同名称的数据库(如my_db_2);不做转储或类似的事情。

答案 3 :(得分:19)

使用类似LiquiBase的内容,这样可以保持对Liquibase文件的版本控制。您可以仅为生产标记更改,并让lb使您的数据库保持最新,无论是生产还是开发,(或您想要的任何方案)。

答案 4 :(得分:6)

在Doctrine下有一个名为Migrations的伟大项目,专为此目的而构建。

它仍处于alpha状态并为php构建。

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

答案 5 :(得分:4)

面对类似的需求,这就是我对数据库版本控制系统的研究:

  1. Sqitch-基于Perl的开源;适用于所有主要数据库,包括PostgreSQL https://github.com/sqitchers/sqitch
  2. Mahout-仅适用于PostgreSQL;开源数据库架构版本控制。 https://github.com/cbbrowne/mahout
  3. Liquibase-另一个开源数据库版本控制软件。免费版本的Datical。 http://www.liquibase.org/index.html
  4. Datical-Liquibase的商业版本-https://www.datical.com/
  5. Box的
  6. Flyway-商业广告。 https://flywaydb.org/
  7. 另一个开源项目https://gitlab.com/depesz/Versioning 作者在此处提供了指南:https://www.depesz.com/2010/08/22/versioning/
  8. 红门变更自动化-仅适用于SQL Server。 https://www.red-gate.com/products/sql-development/sql-change-automation/

答案 6 :(得分:3)

我想做类似的事情,将我的数据库更改添加到我的版本控制系统。

我将遵循弗拉基米尔·霍里科夫"Database versioning best practices"的这篇文章中的想法。总之,我会

  • 将其架构和参考数据存储在源代码管理系统中。
  • 对于每次修改,我们将使用更改
  • 创建单独的SQL脚本

万一有帮助!

答案 7 :(得分:3)

我遇到过这个问题,因为我遇到了类似的问题,其中某些东西接近基于数据库的目录结构,存储文件'我需要git来管理它。它通过云分布,使用复制,因此它的访问点将通过MySQL。

上述答案的要点似乎同样暗示了问题的另一种解决方案,即使用Git管理数据库中的某些内容时忽略了这一点,所以我试图回答这个问题。

Git是一个系统,它实质上存储了一个增量数据库(差异),可以按顺序重新组合,以重现上下文。 git的正常用法假设上下文是一个文件系统,并且那些增量在该文件系统中是不同的,但实际上所有的git都是增量的分层数据库(层次结构,因为在大多数情况下每个增量都是一个提交至少有一位父母,安排在一棵树上。)

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

如果你想管理变更,在数据库中,你有两个不连续的问题,我会单独解决它们(如果我是你)。第一个是架构,第二个是数据(尽管在您的问题中,您声明数据并不是您所关注的事情)。我过去遇到的一个问题是Dev和Prod数据库,其中Dev可以对模式进行渐进式更改,这些更改必须在CVS中记录,并传播到live,以及添加到几个&#39之一;静'表。我们通过拥有一个名为Cruise的第三个数据库来实现这一点,该数据库仅包含静态数据。在任何时候都可以比较Dev和Cruise的模式,并且我们有一个脚本来获取这两个文件的差异并生成包含ALTER语句的SQL文件,以应用它。类似地,任何新数据都可以被提炼为包含INSERT命令的SQL文件。只要添加了字段和表,并且从不删除字段和表,该过程就可以自动生成SQL语句以应用增量。

git生成增量的机制是diff,它将一个或多个增量与文件组合在一起的机制称为merge。如果你能想出一种从不同的上下文中进行差异和合并的方法,git应该可以工作,但正如我们已经讨论过的那样,你可能更喜欢一种能够为你做到这一点的工具。我的第一个想法是解决这个https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#External-Merge-and-Diff-Tools,它详细说明了如何替换git的内部差异和合并工具。我会更新这个答案,因为我想出了一个更好的问题解决方案,但在我的情况下,我希望只需要管理数据更改,因为基于数据库的文件存储可能会发生变化,所以我的解决方案可能不完全符合您的需求。

答案 8 :(得分:3)

看看RedGate SQL Source Control。

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

此工具是一个SQL Server Management Studio管理单元,允许您使用Git将数据库置于Source Control下。

每位用户只需495美元就有点贵,但是有28天免费试用。

请注意 我不以任何方式与RedGate有任何关系。

答案 9 :(得分:2)

如果没有原子性,就无法做到这一点,如果不使用pg_dump或快照文件系统,就无法获得原子性。

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

答案 10 :(得分:2)

在精神上,你想要的可能是Post Facto,它将数据库的版本存储在数据库中。请检查此presentation

该项目显然从未真正去过任何地方,所以它可能不会立即帮助你,但这是一个有趣的概念。我担心这样做是非常困难的,因为即使版本1也必须正确地获取所有细节才能让人们相信他们的工作。

答案 11 :(得分:2)

我发布了一个sqlite工具,可以满足您的要求。它使用自定义diff驱动程序,利用sqlite项目工具'sqldiff',UUID作为主键,并且不使用sqlite rowid。它仍处于alpha状态,因此感谢您的反馈。

Postgres和mysql比较复杂,因为二进制数据保存在多个文件中,如果能够对其进行快照,则可能无效。

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

答案 12 :(得分:1)

我说不。数据可以随时更改。相反,您只应在代码,架构和表定义(create databasecreate table语句)中提交数据模型,并在单元测试中使用示例数据。这是Laravel进行数据库迁移和种子植入的一种方式。

答案 13 :(得分:1)

我们曾经在标准LAMP配置上运行社交网站。我们有一个Live服务器,测试服务器和开发服务器,以及本地开发人员机器。所有这些都是使用GIT管理的。

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

要在GIT下轻松管理所有这些,我们会通过将这些文件夹路径插入.gitignore来忽略二进制文件夹(包含图像的文件夹)。我们在Apache documentroot路径之外还有一个名为SQL的文件夹。在那个SQL文件夹中,我们将来自开发人员的SQL文件放在增量编号中(001.florianm.sql,001.johns.sql,002.florianm.sql等)。这些SQL文件也由GIT管理。第一个sql文件确实包含大量的数据库模式。我们不在GIT中添加用户数据(例如,用户表或注释表的记录),但是在sql文件中(因此通过GIT)维护了诸如配置或拓扑或其他站点特定数据之类的数据。主要是开发人员(他们最了解代码)确定GIT在SQL模式和数据方面没有维护的内容和内容。

当它发布时,管理员登录到开发服务器,将实时分支与开发机器上的所有开发人员和所需分支合并到更新分支,并将其推送到测试服务器。在测试服务器上,他检查Live服务器的更新过程是否仍然有效,并且快速连续,将Apache中的所有流量指向占位符站点,创建数据库转储,将工作目录从“实时”指向“更新” ',将所有新的sql文件执行到mysql中,并将流量重新发送回正确的站点。当所有利益相关方在审核测试服务器后达成一致意见时,管理员在测试服务器和Live服务器上做了同样的事情。之后,他将生产服务器上的实时分支合并到所有服务器上的主分支,并重新定位所有实时分支。开发人员负责自己修改分支机构,但他们通常知道自己在做什么。

如果测试服务器出现问题,例如。合并有太多的冲突,然后代码被还原(将工作分支指回'live')并且从未执行过sql文件。在执行sql文件的那一刻,这被认为是当时的不可逆动作。如果SQL文件无法正常工作,则使用转储恢复数据库(并且开发人员告知,提供经过严格测试的SQL文件)。

今天,我们维护了一个sql-up和sql-down文件夹,具有相同的文件名,开发人员必须测试升级的sql文件,可以同等降级。这最终可以使用bash脚本执行,但如果人眼继续监视升级过程,那么这是一个好主意。

它不是很好,但它可以管理。希望这能让您深入了解真实,实用,相对高可用性的站点。有点过时,但仍然跟着。

答案 14 :(得分:1)

我是怎么做到的:

由于您可以自由选择数据库类型,因此请使用基于文件的数据库,例如:火鸟。

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

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

这样,您可以将数据库架构置于版本控制之下,而无需数据。如果您更改架构,则只需更改模板DB

答案 15 :(得分:1)

在git版本控制下存储每个级别的数据库更改就像在每次提交时推送整个数据库一样,并且恢复整个数据库拉。 如果您的数据库非常容易发生重大变化,并且您无法放松它们,则只需更新 pre_commit post_merge 挂钩即可。 我对我的一个项目做了同样的事情,你可以找到方向here

答案 16 :(得分:1)

我在个人项目中所做的是,我将整个数据库存储到dropbox,然后指向MAMP,WAMP工作流程,直接从那里使用它。这样,数据库始终是最新的,我需要做什么一些发展。但那只是开发者!直播网站正在使用自己的服务器! :)

答案 17 :(得分:1)

我建议neXtep用于控制数据库的版本,它有一套很好的文档和论坛,解释了如何安装和遇到的错误。我已经测试了它的postgreSQL 9.1和9.3,我能够让它适用于9.1但是9.3它似乎不起作用。

答案 18 :(得分:1)

答案 19 :(得分:1)

我认为X-Istence正在走上正轨,但您可以对此策略进行一些改进。首先,使用:

$pg_dump --schema ... 

转储表,序列等,并将此文件置于版本控制之下。您将使用它来分离分支之间的兼容性更改。

接下来,为包含配置 required 的表集执行数据转储,以便应用程序运行(应该可能跳过用户数据等),例如表单默认值和其他非用户可修改的数据数据。您可以使用以下选项执行此操作:

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

这是一个好主意,因为当数据库在执行完整数据转储时达到100Mb +时,repo会变得非常笨重。更好的方法是备份测试应用程序所需的最小数据集。如果您的默认数据非常大,但这可能仍会导致问题。

如果您绝对需要在repo中放置完整备份,请考虑在源树之外的分支中执行此操作。尽管如此,一个外部备份系统可能最适合使用匹配的svn rev。

另外,我建议在二进制文件中使用文本格式转储以进行修订(至少对于模式),因为这些转换更容易区分。您可以在登记前始终压缩这些以节省空间。

最后,如果您还没有,请查看postgres backup documentation。您评论备份“数据库”而不是转储的方式让我想知道您是否在考虑基于文件系统的备份(请参阅23.2部分了解警告)。

答案 20 :(得分:0)

以下是我在项目中尝试做的事情:

  • 单独的数据和架构以及默认数据。

数据库配置存储在不受版本控制(.gitignore)

的配置文件中

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

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

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

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

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

理论上(这就是我要找的)你可以 每次更改后转储数据库模式(手动,结合,git挂钩(可能在提交之前)) (并且仅在一些非常特殊的情况下创建更新脚本)

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

答案 21 :(得分:0)

  

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

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

答案 22 :(得分:0)

使用iBatis Migrations(manualshort tutorial video)之类的工具,它允许您在项目的整个生命周期中对数据库进行的更改进行版本控制,而不是比数据库本身。

这允许您有选择地将单个更改应用于不同的环境,保留更改在哪些环境中的更改日志,创建脚本以应用更改A到N,回滚更改等。

答案 23 :(得分:0)

一段时间以来,我一直在寻找与Postgres(或SQL数据库)相同的功能,但是我发现没有足够的工具适合(简单直观)。这可能是由于数据存储方式的二进制性质。 Klonio听起来很理想,但看起来已经死了。 Noms DB看起来很有趣(并且还活着)。还可以看看Irmin(基于OCaml的Git属性)。

尽管这不能解决问题,因为它可以与Postgres一起使用,但是请检查Flur.ee数据库。它具有“时间旅行”功能,可让您从任意时间点查询数据。我猜它应该能够与“分支”模型一起工作。

该数据库最近被开发用于区块链用途。由于区块链的性质,数据需要以增量方式记录,这正是git的工作方式。他们是targeting an open-source release in Q2 2019

  

Because each Fluree database is a blockchain, it stores the entire history of every transaction performed. This is part of how a blockchain ensures that information is immutable and secure

答案 24 :(得分:0)

2019年8月26日更新:

Netlify CMS是在GitHub上实现的,可以在此处找到示例实现,以及有关其实现方式的所有信息netlify-cms-backend-github