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

时间:2008-08-08 20:50:03

标签: mysql svn

我很难找到如何在开发,测试和生产服务器之间管理数据库模式和数据的好例子。

这是我们的设置。每个开发人员都有一个运行我们的app和MySQL数据库的虚拟机。他们的个人沙箱可以随心所欲。目前,开发人员将对SQL模式进行更改,并将数据库转储到他们提交到SVN的文本文件中。

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

我们有一个运行“候选版本”的测试(虚拟)服务器。部署到测试服务器目前是一个非常手动的过程,通常涉及我从SVN加载最新的SQL并进行调整。此外,测试服务器上的数据不一致。您最终会得到最后一位开发人员在他的沙盒服务器上提供的测试数据。

一切都崩溃的是部署到生产。由于我们无法使用测试数据覆盖实时数据,因此需要手动重新创建所有架构更改。如果有大量的架构更改或转换脚本来操纵数据,这可能会变得非常毛茸茸。

如果问题只是架构问题,那么问题就更容易了,但数据库中的“基础”数据也会在开发过程中更新,例如安全和权限表中的元数据。

这是我在实现持续集成和一步构建方面所看到的最大障碍。 如何解决它?


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


感谢您参考塔伦蒂诺。我不是在.NET环境中,但我发现他们的DataBaseChangeMangement wiki page非常有帮助。特别是Powerpoint Presentation (.ppt)

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


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

14 个答案:

答案 0 :(得分:51)

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

  1. 编写所有架构更改的脚本,让CI服务器在数据库上运行这些脚本。有一个版本表来跟踪当前的数据库版本,并且只有在适用于较新版本时才执行脚本。

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

答案 1 :(得分:28)

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

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

答案 2 :(得分:13)

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

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

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

答案 3 :(得分:8)

本书Refactoring Databases: Evolutionary Database Design可能会为您提供有关如何管理数据库的一些建议。在http://martinfowler.com/articles/evodb.html

也可读取简短版本

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

答案 4 :(得分:4)

  • 按如下方式命名数据库 - db_dev,db_test,db_qa,db_prod(显然你永远不应该硬编码数据库名称
  • 因此,您甚至可以在同一台物理服务器上部署不同类型的数据库(我不建议这样做,但如果资源紧张,您可能需要......)
  • 确保您能够自动在这些数据之间移动数据
  • 将db创建脚本与population分开=始终可以从头开始重新创建db并填充它(从旧的db版本或外部数据源
  • 不要在代码中使用硬编码连接字符串(甚至不在配置文件中) - 在配置文件连接字符串模板中使用,你动态填充,每次需要重新编译的application_layer的重新配置都是BAD
  • 确实使用数据库版本控制和数据库对象版本控制 - 如果你能负担得起它使用现成的产品,如果没有自己开发的东西
  • 跟踪每个DDL更改并将其保存到某个历史记录表(example here
  • 每日备份!测试您能够以多快的速度恢复从备份中丢失的内容(使用自动恢复脚本
  • 即使您的DEV数据库和PROD具有完全相同的创建脚本,您也会遇到数据问题,因此允许开发人员创建prod的精确副本并使用它(我知道我会收到这个的缩写,但是当屎袭击粉丝时,思维模式和业务流程的改变将花费你更少的钱 - 所以迫使编码人员合法地下标,无论它做什么,但确保这一点

答案 5 :(得分:3)

这是我一直不满意的事情 - 我们解决这个问题的方法。几年来,我们为每个版本维护了一个单独的更改脚本。此脚本将包含上一个生产版本的增量。随着应用程序的每个版本的发布,版本号都会增加,如下所示:

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

这很好用,直到我们开始维护两个开发线:用于新开发的Trunk / Mainline,以及用于修复bug,短期增强等的维护分支。不可避免地,需要对模块中的模式进行更改。科。此时,我们已经在Trunk中使用了dbChanges_n + 1.sql,因此我们最终采用了如下方案:

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

同样,这种方法运作得很好,直到有一天我们抬头看到主线上有42个delta脚本,分支中有10个delta脚本。哎呀!

这些天我们只维护一个delta脚本并让SVN版本 - 即我们用每个版本覆盖脚本。我们回避在分支机构中进行架构更改。

所以,我对此也不满意。我非常喜欢Rails迁移的概念。我对LiquiBase非常着迷。它支持增量数据库重构的概念。值得一看,我很快就会详细介绍它。有人有经验吗?我很想知道你的结果。

答案 6 :(得分:3)

您还可以使用SQL Compare之类的工具来编写各种版本数据库之间的差异,以便在版本之间快速迁移

答案 7 :(得分:2)

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

开发人员使用私有数据库在VM中开发。

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

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

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

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

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

我们做什么:

我们采用沙箱数据库的模式转储。 然后是一个sql数据转储。 我们将其与之前的基线区分开来。 这对增量是将n-1升级为n。

我们配置转储和增量。

因此,要安装版本N CLEAN,我们将转储运行到空数据库中。 要修补,请应用干预补丁。

(Juha提到Rail有一个记录当前数据库版本的表的想法是一个很好的,应该让安装更新不那么充满。)

在beta测试之前必须审查Deltas和转储。 我看不到任何解决方法,因为我看到开发人员为自己将数据库插入数据库。

答案 8 :(得分:1)

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

答案 9 :(得分:1)

查看dbdeploy,已有Java和.net工具,您可以按照SQL文件布局和架构版本表的标准编写python版本。

答案 10 :(得分:1)

我担心我会同意其他海报。开发人员需要编写他们的更改脚本。

在许多情况下,简单的ALTER TABLE不起作用,您需要修改现有数据 - 开发人员需要了解需要哪些迁移并确保它们的编写正确(当然,您需要在发布周期中的某一点)。

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

我不知道如何将其挂钩到CI服务器中。也许您的CI服务器需要具有已知的构建快照,它将恢复到每晚,然后应用此后的所有更改。这可能是最好的,否则破坏的迁移脚本不仅会破坏当晚的构建,还会破坏所有后续版本。

答案 11 :(得分:0)

我编写了一个工具(通过挂钩Open DBDiff)来比较数据库模式,并会向您建议迁移脚本。如果您进行了删除或修改数据的更改,它将引发错误,但会为脚本提供建议(例如,当新模式中缺少某列时,它将检查该列是否已重命名并创建xx - 生成包含重命名语句的script.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 ExportLinqToSql CreateDatabase或其他内容)。然后使用创建的_dev和_next DB执行migrationscriptgenerator。用于迁移的SQL更新脚本。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

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

此工具自动化下一个流程

  1. 对于每个db scheme get scheme ddls
  2. 将其置于版本控制
  3. 手动解决的实例之间的更改