2008-08-08 81 views
154

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

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

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

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

凡是发生故障的部分都是生产部署。由于我们无法用测试数据覆盖实时数据,因此需要手动重新创建所有模式更改。如果有大量的模式更改或转换脚本来操纵数据,这可能会变得非常多毛。

如果问题只是模式,它会是一个更容易的问题,但是在开发过程中还会更新数据库中的“基础”数据,例如安全和权限表中的元数据。

这是我在迈向持续集成和一步构建时遇到的最大障碍。 解决了吗?


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


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

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


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

+0

相关:HTTP:// stackoverflow.com/questions/52583/best-tool-for-synchronizing-mysql-databases – 2012-08-21 09:31:36

回答

46

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

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

  2. 使用迁移解决方案。这些解决方案因语言而异,但对于.NET,我使用Migrator.NET。这使您可以对数据库进行版本升级并在版本之间上下移动。您的模式在C#代码中指定。

26

你的开发人员编写的每一个错误/功能上他们的工作变化的脚本(架构和数据的变化),不只是单纯的转储整个数据库源代码控制。这些脚本会将当前生产数据库升级到开发中的新版本。

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

1

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

+1

死链接。该项目现在似乎在这里:https://bitbucket.org/headspringlabs/tarantino/wiki/Home或这里:https://github.com/HeadspringLabs/Tarantino – 2014-03-18 21:50:22

12

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

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

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

3

这是我一直不满意的东西 - 我们解决这个问题的方法。几年来,我们为每个版本保留一个单独的更改脚本。该脚本将包含上一个产品版本的变更。随着应用程序的每个版本,版本号会增加,给类似如下:

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

直到我们开始维护两条线的开发之前,这种方法运行得很好:新的开发中的Trunk/Mainline,以及bug修复,短期增强等的维护分支。不可避免地, ges到分支中的模式。在这一点上,我们已经有了在树干dbChanges_n + 1.SQL,所以我们结束了类似下面的方案去:

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

同样,这已经足够好了,直到我们有一天,我们一抬头,看见在主线和42个三角洲脚本10支。哎呀!

现在我们简单地维护一个delta脚本并让SVN版本 - 即我们用每个版本覆盖脚本。我们避免在分支机构中进行模式更改。

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

1

查看dbdeploy,已经有Java和.net工具可用,您可以按照他们的SQL文件布局和模式版本表标准来编写您的Python版本。

2

我们有一个非常类似于OP的设置。

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

[开发商将很快提交到私有分支]

测试是(在虚拟机的服务器上托管的实际) 在不同的机器上运行

测试[很快就会被哈德森CI服务器运行]通过加载参考转储到数据库。 应用开发者架构补丁 然后应用开发者数据补丁

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

生产作为安装者部署给客户。

我们做什么:

我们把我们的沙箱数据库的模式转储。 然后一个sql数据转储。 我们将其与之前的基准进行比较。 那对deltas是将n-1升级到n的。

我们配置转储和增量。

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

(尤哈提及具有表记录当前DB版本的轨道的想法是好的,应该使安装更新少误人子弟。)

三角洲和堆放有beta测试之前进行审查。 我看不到任何解决方法,因为我已经看到开发人员将测试帐户插入到数据库中。

1

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

在许多情况下,一个简单的ALTER TABLE将不起作用,您还需要修改现有数据 - 开发人员需要了解需要什么迁移并确保它们正确编写脚本(当然,您需要仔细测试在发布周期的某个时间点)。此外,如果您有任何意义,您可以让开发人员对其更改进行脚本回滚,以便在需要时还原它们。这也应该进行测试,以确保它们的回滚不仅没有错误地执行,而且使数据库保持与先前相同的状态(这并非总是可行或可取的,但大多数情况下是一个很好的规则) 。

如何将其挂接到CI服务器,我不知道。也许你的CI服务器需要有一个已知的构建快照,它会在每天晚上恢复,然后应用所有更改。这可能是最好的,否则破坏的迁移脚本不仅会打破当晚的构建,而且会破坏所有后续构建。

3

你也可以看看使用像SQL Compare工具脚本数据库的各个版本之间的区别,让您在版本之间

+1

SQLCompare是用于SQL Server。 Red Gate的MySQL工具是调用MySQL Compare和cam在这里找到的:http://mysql-compare.com/ – 2011-08-18 21:45:29

0

我写了一个工具(挂接到Open DBDiff)快速迁移比较数据库模式,并向您建议迁移脚本。如果你做了一个删除或修改数据的改变,它会抛出一个错误,但是为脚本提供一个建议(例如,当一个列在新模式中丢失时,它将检查列是否已被重命名并创建xx - 生成包含重命名语句的script.sql.suggestion)。

http://code.google.com/p/migrationscriptgenerator/ SQL Server只恐怕:(这也是很不成熟,但它是非常低的摩擦

我用它是有一个SQL的方式(特别是如果你有塔伦蒂诺或http://code.google.com/p/simplescriptrunner/结合起来)脚本项目在你的.sln中,你也可以在本地做一个db_next数据库(使用Management Studio或NHibernate Schema ExportLinqToSql CreateDatabase或其他),然后用_dev和_next数据库执行migrationscriptgenerator,创建SQL更新脚本

7

Refactoring Databases: Evolutionary Database Design可能会给你一些想法,如何管理e数据库。短版本也可读http://martinfowler.com/articles/evodb.html

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

4
  • 名称的数据库如下 - db_dev,db_test,db_qa,db_prod(很显然,你永远不应该硬编码DB名
  • 因此,你将能够部署甚至不同类型的同一物理服务器上数据库的的(我做但是你可能不得不......如果资源紧张的话)
  • 确保你能够在这些数据之间自动移动数据
  • 将数据库创建脚本与总体分开=应该总是可以重新创建db从头开始并填充它(从旧的db版本或外部数据源
  • 不要在代码中使用硬编码连接字符串(即使不在配置文件中) - 在配置文件中使用连接字符串模板,您可以动态填充它,需要重新编译的application_layer的每个重新配置都是坏BAD
  • 使用数据库版本和版本数据库对象 - 如果你能负担得起使用现成的产品,如果每个DDL变化对自己的
  • 轨迹不发展的东西,并保存到一些历史表(example here
  • 每日备份!测试你能够以多快的速度恢复备份丢失的东西(使用自动恢复脚本即使你的DEV数据库和PROD具有完全相同的创建脚本,你也会遇到数据问题,因此开发人员可以创建准确的(我知道我会接受这个问题的缺点,但是当思念和业务流程发生变化时,如果狗屎碰上粉丝,那么你的成本就会降低很多 - 所以强制编码人员合法地标明它所做的任何事情,但是确保这一
0

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

0

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

这个工具自动下道工序

  1. ,每分贝方案GET方案的DDL
  2. 把它放在版本控逆变实例之间

改变手动解决