我们如何在开发,测试和生产中管理数据库?

时间:2020-03-05 18:38:41  来源:igfitidea点击:

我一直很难尝试找到有关如何在开发,测试和生产服务器之间管理数据库架构和数据的良好示例。

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

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

我们有一台运行"虚拟候选版本"的测试(虚拟)服务器。当前,部署到测试服务器是一个非常手动的过程,通常需要我从SVN加载最新的SQL并进行调整。另外,测试服务器上的数据不一致。最后,我们将获得最后一个要提交的开发人员在其沙箱服务器上拥有的测试数据。

一切失败的地方就是部署到生产。由于我们无法用测试数据覆盖实时数据,因此需要手动重新创建所有架构更改。如果存在大量的架构更改或者转换脚本来操纵数据,那么这可能会变得很麻烦。

如果问题仅仅是模式,那将是一个更简单的问题,但是数据库中也存在"基础"数据,这些数据也在开发过程中进行了更新,例如安全性和权限表中的元数据。

这是我在迈向持续集成和一步构建的最大障碍。我们如何解决?

后续问题:如何跟踪数据库版本,以便知道运行哪些脚本来升级给定的数据库实例?像Lance一样的版本表是否在标准程序下面提到?

感谢我们引用Tarantino。我不在.NET环境中,但是我发现他们的DataBaseChangeMangement Wiki页面非常有用。特别是此Powerpoint演示文稿(.ppt)

我要编写一个Python脚本,该脚本将对照数据库中的表检查给定目录中的* .sql脚本名称,并根据构成第一部分的整数顺序运行不存在的* .sql脚本名称文件名。如果这是一个非常简单的解决方案(我怀疑会这样),那么我将其发布在这里。

我有一个工作脚本。如果数据库不存在,它将处理数据库初始化,并根据需要运行升级脚本。还有用于擦除现有数据库和从文件导入测试数据的开关。它大约有200行,所以我不会发布(尽管有兴趣的话我可以将其放在pastebin上)。

解决方案

回答

有几个不错的选择。我不会使用"还原备份"策略。

  • 编写所有模式更改的脚本,并让CI服务器在数据库上运行这些脚本。有一个版本表来跟踪当前的数据库版本,并且仅当脚本用于较新的版本时才执行。
  • 使用迁移解决方案。这些解决方案因语言而异,但是对于.NET,我使用Migrator.NET。这使我们可以对数据库进行版本控制,并在不同版本之间上下移动。架构是用C#代码指定的。

回答

开发人员需要针对他们处理的每个错误/功能编写更改脚本(模式和数据更改),而不仅仅是将整个数据库转储到源代码管理中。这些脚本会将当前的生产数据库升级到开发中的新版本。

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

回答

如果我们在.NET环境中,则解决方案是Tarantino。它在NANT构建中处理所有这些(包括要安装的sql脚本)。

回答

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

首先是所谓的迁移文件,它们基本上将数据库模式和数据从版本N转换为版本N + 1(或者从版本N + 1降级为N的情况)。数据库具有表,该表告知当前版本。

在进行单元测试之前,总是擦拭干净测试数据库,并使用文件中的固定数据填充测试数据库。

回答

这是我一直不满意的解决方案。几年来,我们为每个版本维护一个单独的更改脚本。该脚本将包含上一个生产版本的增量。在该应用程序的每个发行版中,版本号都会增加,并给出以下内容:

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

在我们开始维护两条开发线之前,这已经足够有效了:用于新开发的Trunk / Mainline以及用于错误修复,短期增强等的维护分支。不可避免地,需要对分支中的架构进行更改。此时,我们在Trunk中已经有了dbChanges_n + 1.sql,因此最终采用了以下方案:

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

再次,它运行良好,直到有一天我们查找并在主线中看到了42个增量脚本,在分支中看到了10个。啊!

如今,我们仅维护一个增量脚本并让SVN对其进行版本化,即我们在每个发行版中都覆盖了该脚本。而且,我们避免在分支机构中进行架构更改。

因此,我也不满意。我真的很喜欢从Rails迁移的概念。我对LiquiBase十分着迷。它支持增量数据库重构的概念。值得一看,我将在稍后详细介绍。有人有经验吗?我很想知道结果。

回答

查看dbdeploy,已经有Java和.net工具,我们可以遵循它们关于SQL文件布局和架构版本表的标准,并编写python版本。

回答

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

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

[开发者将很快进入私人分支机构]

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

通过将参考转储加载到数据库中进行测试。
应用开发人员架构补丁
然后应用开发人员数据补丁

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

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

我们所做的:

我们对沙箱数据库进行模式转储。
然后是一个sql数据转储。
我们将其与先前的基准进行比较。
这对增量将n-1升级为n。

我们配置转储和增量。

因此,要安装版本N CLEAN,我们将转储运行到一个空的数据库中。
要打补丁,请应用中间的补丁。

(Juha提到了Rail的想法,即拥有一张记录当前数据库版本的表的想法很不错,应该减少安装更新的麻烦。)

在Beta测试之前,必须对三角洲和垃圾场进行审查。

回答

我看不到任何解决方法,因为我已经看到开发人员自己将测试帐户插入数据库。

恐怕我同意其他海报。开发人员需要编写自己的更改脚本。

在许多情况下,简单的ALTER TABLE无法使用,我们还需要修改现有数据,开发人员也需要考虑所需的迁移,并确保正确编写了脚本(当然,我们需要在发布周期)。

此外,如果我们有任何判断力,还可以让开发人员编写脚本回滚以对其进行更改,以便在需要时可以将其还原。还应该对此进行测试,以确保它们的回滚不仅执行没有错误,而且使数据库保持与以前相同的状态(这并不总是可能或者合乎需要的,但在大多数情况下是个好规则) 。

回答

我不知道如何将其连接到CI服务器。也许CI服务器需要具有一个已知的构建快照,该快照将还原到每晚,然后应用此后的所有更改。那可能是最好的,否则损坏的迁移脚本不仅会破坏当晚的构建,还会破坏所有后续构建。

回答

我们也可以考虑使用SQL Compare之类的工具来编写数据库不同版本之间的差异的脚本,从而使我们可以在不同版本之间快速迁移

我编写了一个工具(通过连接到Open DBDiff)比较数据库模式,并向我们建议迁移脚本。如果我们进行更改以删除或者修改数据,它将引发错误,但会为脚本提供建议(例如,当新架构中缺少列时,它将检查该列是否已重命名并创建xx生成的脚本.sql.suggestion包含重命名语句)。

恐怕只有http://code.google.com/p/migrationscriptgenerator/ SQL Server :(它也很漂亮,但是摩擦很小(尤其是将它与Tarantino或者http://code.google结合使用时) .com / p / simplescriptrunner /)

回答

我使用它的方法是在.sln中有一个SQL脚本项目。我们还可以在本地进行db_next数据库更改(使用Management Studio或者NHibernate Schema Export或者LinqToSql CreateDatabase等)。然后,使用创建的_dev和_next数据库执行migrationscriptgenerator。用于迁移的SQL更新脚本。

《重构数据库:演化数据库设计》一书可能会为我们提供有关如何管理数据库的一些想法。在http://martinfowler.com/articles/evodb.html上也可以阅读简短版本

回答

  • 如下命名数​​据库-db_dev,db_test,db_qa,db_prod(显然,我们永远不应该对数据库名称进行硬编码
  • 因此,我们甚至可以在同一台物理服务器上部署不同类型的数据库(我不建议这样做,但是如果资源紧张,我们可能必须...)
  • 确保我们将能够在这些数据之间自动移动数据
  • 从填充中分离数据库创建脚本=应该总是有可能从头开始重新创建数据库并填充它(从旧数据库版本或者外部数据源
  • 不要在代码中使用硬编码连接字符串(即使在配置文件中也不使用)-在配置文件中使用连接字符串模板(我们会动态填充),需要重新编译的application_layer的每个重新配置都是BAD
  • 确实使用数据库版本控制和数据库对象版本控制-如果我们负担得起的话,请使用现成的产品,如果不是自己开发某些产品
  • 跟踪每个DDL更改并将其保存到一些历史记录表中(此处为示例)
  • 每日备份!测试我们能够多快地恢复备份中丢失的内容(使用自动还原脚本)
  • 即使DEV数据库和PROD具有完全相同的创建脚本,我们也会在数据方面遇到问题,因此允许开发人员创建prod的确切副本并使用它(我知道我会收到与此有关的弊端,但是在思维定势和业务流程将使成本降低很多-强迫编码人员合法地进行标刻,但要确保这一点

回答

在一个PHP + MySQL项目中,我已经在数据库中存储了数据库修订版本号,当程序连接到数据库时,它将首先检查该修订版本。如果程序需要其他版本,它将打开一个页面,用于升级数据库。每次升级都是在PHP代码中指定的,它将更改数据库架构并迁移所有现有数据。

段落数量不匹配