如何管理开发、测试和生产环境中的数据库?

我花了很长时间才找到了一些很好的例子,说明如何在开发、测试和生产服务器之间管理数据库模式和数据。

这是我们的设备。每个开发人员都有一个运行我们的应用程序和 MySQL 数据库的虚拟机。他们想做什么就做什么,这是他们的私事。目前,开发人员将对 SQL 模式进行更改,并将数据库转储到一个文本文件中,然后提交到 SVN 中。

我们希望部署一个持续集成开发服务器,它将始终运行最新提交的代码。如果我们现在这样做,它将为每次构建从 SVN 重新加载数据库。

我们有一个运行“候选版本”的测试(虚拟)服务器部署到测试服务器目前是一个非常手工的过程,通常需要我从 SVN 加载最新的 SQL 并对其进行调整。而且,测试服务器上的数据不一致。您最终将获得最后提交的开发人员在其沙箱服务器上拥有的任何测试数据。

在这里,一切都会崩溃,这就是部署到生产环境的过程。由于我们不能用测试数据覆盖活动数据,因此需要手动重新创建所有模式更改。如果存在大量的模式更改或转换脚本来操作数据,那么这可能会非常麻烦。

如果问题只是模式,问题会更简单,但是数据库中有“基础”数据,在开发过程中也会更新,比如安全性和权限表中的元数据。

这是我看到的向持续集成和一步构建发展的最大障碍。 如何解决这个问题?


接下来的问题是: 如何跟踪数据库版本,以便知道要运行哪些脚本来升级给定的数据库实例?Lance 提到的版本表是否低于标准程序?


谢谢你提到塔伦蒂诺。我没有。NET 环境下,但我发现他们的 DataBaseChangeMangement 维基页面是非常有帮助的。尤其是这个 简报(. ppt)

我将编写一个 Python 脚本,根据数据库中的一个表检查给定目录中的 *.sql脚本的名称,并根据构成文件名第一部分的整数来运行那些不存在的脚本。如果它是一个相当简单的解决方案,我怀疑它将是,然后我会张贴在这里。


我已经准备好了剧本。如果数据库不存在,它将处理数据库的初始化,并根据需要运行升级脚本。还有用于擦除现有数据库和从文件导入测试数据的开关。它大约有200行,所以我不会发布它(尽管如果有兴趣的话,我可能会把它贴在粘贴面上)。

39549 次浏览

有几个不错的选择,我不会使用“恢复备份”策略。

  1. 编写所有模式更改的脚本,并让 CI 服务器在数据库上运行这些脚本。有一个版本表来跟踪当前的数据库版本,只有当脚本是针对较新的版本时才执行脚本。

  2. 使用迁移解决方案。这些解决方案因语言的不同而不同,但。NET 我使用的是 Migator.NET。这允许您对数据库进行版本控制,并在不同版本之间上下移动。您的模式是在 C # 代码中指定的。

您的开发人员需要为他们处理的每个 bug/特性编写更改脚本(模式和数据更改) ,而不仅仅是将整个数据库转储到源代码控制中。这些脚本将把当前的生产数据库升级到正在开发的新版本。

生成过程可以将生产数据库的一个副本还原到适当的环境中,并在其上运行源代码管理中的所有脚本,从而将数据库更新到当前版本。我们每天都这样做,以确保所有脚本正确运行。

如果你在。NET 环境下,那么解决方案是 塔伦蒂诺(存档)。它在 NANT 构建中处理所有这些问题(包括要安装哪些 sql 脚本)。

看看 Ruby on Rails 是如何做到这一点的。

首先,存在所谓的迁移文件,它基本上将数据库模式和数据从版本 N 转换到版本 N + 1(或者从版本 N + 1降级到 N)。数据库有一个告诉当前版本的表。

在进行单元测试之前,测试数据库总是被清除干净,并用来自文件的固定数据填充。

这是我一直不满意的东西-我们对这个问题的解决方案是。几年来,我们为每个版本维护一个单独的变更脚本。这个脚本将包含上一个生产版本中的增量。随着应用程序的每次发布,版本号都会增加,产生如下结果:

  • DbChanges _ 1. sql
  • DbChanges _ 2. sql
  • ...
  • DbChanges _ n. sql

在我们开始维护两条开发线路之前,这个工作已经足够好了: 针对新开发的 Trunk/Mainline,以及针对 bug 修复、短期增强等的维护分支。不可避免地,需要对分支中的模式进行更改。此时,我们已经有了 dbChanges _ n + 1。Sql,因此我们最终采用了如下方案:

  • DbChanges _ n.1. sql
  • DbChanges _ n.2. sql
  • ...
  • DbChanges _ n.3. sql

同样,这种方法工作得很好,直到有一天我们查看并在主线中看到42个 delta 脚本,在分支中看到10个。啊!

现在,我们只是维护一个 delta 脚本,并让 SVN 对其进行版本控制——也就是说,我们用每个版本覆盖该脚本。并且我们回避在分支中进行模式更改。

所以,我对这个也不满意。我非常喜欢从 Rails 迁移的概念。我对 液体基地非常着迷。它支持增量数据库重构的概念。值得一看,我很快会详细研究的。有人有这方面的经验吗?我很想知道你的结果。

看看 数据库部署,有 Java 和。Net 工具已经可用,您可以遵循其标准的 SQL 文件布局和模式版本表,并编写您的 Python 版本。

我们有一个与 OP 非常相似的设置。

开发人员使用 VM 和私有 DB 进行开发。

(开发商很快将投资于私营分支机构)

测试在不同的机器上运行(实际上是在托管在服务器上的 VM 中) [即将由 Hudson CI 服务器运行]

通过将引用转储加载到 db 中进行测试。 应用开发人员模式补丁 然后应用开发人员的数据补丁

然后运行单元测试和系统测试。

生产作为安装程序部署到客户手中。

我们的工作:

我们获取沙箱 DB 的模式转储。 然后是 sql 数据转储。 我们将其与之前的基线进行区分。 那对 delta 就是把 n-1升级为 n。

我们配置转储和增量。

因此,为了安装版本 N CLEAN,我们将转储运行到一个空数据库中。 要修补,应用中间的修补程序。

(Juha 提到 Rail 的想法是用一个表来记录当前的 DB 版本,这是一个很好的想法,可以减少安装更新的麻烦。)

三角洲和转储必须审查之前,测试。 我看不出有什么办法可以解决这个问题,因为我已经看到开发人员为自己将测试帐户插入到 DB 中。

恐怕我同意其他海报的观点。开发人员需要为他们的更改编写脚本。

在许多情况下,一个简单的 ALTER TABLE 不起作用,你还需要修改现有的数据——开发人员需要考虑需要什么迁移,并确保它们的脚本是正确的(当然,你需要在发布周期的某个时刻仔细测试这一点)。

此外,如果您有任何意识的话,您将让您的开发人员为他们的更改编写回滚脚本,以便在需要时可以恢复它们。这也应该进行测试,以确保它们的回滚不仅执行时没有错误,而且使 DB 保持与以前相同的状态(这并不总是可能或可取的,但在大多数情况下是一个很好的规则)。

怎么连上线人服务器,我不知道。也许您的 CI 服务器需要有一个已知的构建快照,它每晚都会恢复该快照,然后应用此后的所有更改。这可能是最好的,否则一个坏掉的迁移脚本不仅会破坏当晚的构建,还会破坏所有后续的构建。

您还可以考虑使用像 SQL 比较这样的工具来编写数据库不同版本之间的差异脚本,从而允许您在不同版本之间快速迁移

我已经编写了一个工具(通过连接到 打开 DBDiff)比较数据库模式,并将向您建议迁移脚本。如果您做了一个删除或修改数据的更改,它将抛出一个错误,但是会为脚本提供一个建议(例如,当新模式中缺少一列时,它将检查该列是否已被重命名,并创建包含重命名语句的 xx 生成 script.sql.construction)。

Http://code.google.com/p/migrationscriptgenerator/ 只有我害怕 SQL Server: (它也是相当 alpha 的,但是摩擦非常小(特别是如果你把它和 Tarantino 或者 http://code.google.com/p/simplescriptrunner/结合起来)

我使用它的方式是在您的。(西班牙语)。您还有一个本地的 db _ next 数据库,您可以对其进行更改(使用 ManagementStudio 或 NHibernate 模式导出创建数据库等)。然后使用 _ dev 和 _ next DBs 执行迁移脚本生成器,这将创建。用于迁移的 SQL 更新脚本。

重构数据库: 进化数据库设计这本书可能会给你一些关于如何管理数据库的想法。一个简短的版本也是可读的在 http://martinfowler.com/articles/evodb.html

在一个 PHP + M ySQL 项目中,我将数据库修订号存储在数据库中,当程序连接到数据库时,它将首先检查修订。如果程序需要不同的修订版本,它将打开一个页面来升级数据库。每次升级都在 PHP 代码中指定,这将更改数据库模式并迁移所有现有数据。

  • 将您的数据库命名为-dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>(显然您永远不应该硬编码 db 名称
  • 因此,您甚至可以在同一个物理服务器上部署不同类型的数据库(我不建议这样做,但是如果资源紧张,您可能必须这样做)
  • 确保您能够在这些数据之间自动移动数据
  • 将 db 创建脚本与填充分离 = 应该总是可以从头开始重新创建 db 并填充它(从旧的 db 版本或外部数据源)
  • 不要在代码中使用硬代码连接字符串(甚至不要在配置文件中使用)-在配置文件连接字符串模板中使用,您可以动态填充这些模板,每次需要重新编译的 application _ Layer 重新配置都是 BAD
  • 使用数据库版本控制和数据库对象版本控制-如果你可以负担得起,使用现成的产品,如果不开发自己的东西
  • 跟踪每个 DDL 更改并将其保存到某个历史表(举个例子)中
  • 每日备份!测试恢复备份中丢失的内容的速度(使用自动恢复脚本)
  • 即使你的 DEV 数据库和 PROD 有完全相同的创建脚本,你会有问题的数据,所以允许开发人员创建产品的确切副本,并发挥它(我知道我会收到这一个的负面影响,但改变思维模式和业务流程将花费你更少的时候,狗屎的风扇-所以迫使程序员合法下标,不管它做什么,但确保这一个

我们使用命令行 Mysql-diff: 它输出两个数据库模式(来自 live DB 或脚本)之间的差异作为 ALTER 脚本。Mysql-diff 在应用程序启动时执行,如果模式发生更改,它将向开发人员报告。因此开发人员不需要手动编写 ALTERs,模式更新是半自动进行的。

对于 Oracle 数据库,我们使用 Oracle-ddl2svn工具。

这个工具自动化了下一个过程

  1. 对于每一个 db 方案获得方案 ddls
  2. 将其置于版本控制之下

手动解决实例之间的更改