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

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

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

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

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

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

这是我在走向持续集成和一步构建过程中看到的最大障碍。怎么办 解决这个问题?


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


感谢您对塔伦蒂诺的提及。我不在.NET环境中,但我找到了他们 DataBaseChangeMangement 维基页面 非常有帮助。尤其是这个 幻灯片演示 (.ppt)

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


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

有帮助吗?

解决方案

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

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

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

其他提示

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

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

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

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

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

这本书 重构数据库:进化数据库设计 可能会给您一些有关如何管理数据库的想法。简短版本也可以在以下位置阅读 http://martinfowler.com/articles/evodb.html

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

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

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

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

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

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

同样,这种方法运行得很好,直到有一天我们查找并发现主线中有 42 个增量脚本,分支中有 10 个。啊啊!

如今,我们只是维护一个 delta 脚本并让 SVN 对其进行版本控制 - 即我们在每次发布时都会覆盖脚本。我们回避在分支中进行架构更改。

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

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

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

开发人员在具有私有数据库的虚拟机中进行开发。

[开发人员很快将致力于建立私人分支机构]

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

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

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

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

我们所做的:

我们对沙盒数据库进行模式转储。然后是sql数据转储。我们将其与之前的基线进行比较。这对增量是将 n-1 升级到 n。

我们配置转储和增量。

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

( Juha 提到 Rail 的想法是用一张表记录当前数据库版本,这是一个很好的想法,应该可以让安装更新不再那么麻烦。)

在 Beta 测试之前必须审查 Delta 和转储。我看不到任何解决这个问题的方法,因为我看到开发人员自己将测试帐户插入到数据库中。

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

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

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

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

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

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

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

http://code.google.com/p/migrationscriptgenerator/ 恐怕只有 SQL Server :( 它也相当 alpha,但摩擦非常低(特别是如果你将它与 Tarantino 或 http://code.google.com/p/simplescriptrunner/)

我使用它的方法是在 .sln 中有一个 SQL 脚本项目。您在本地还有一个 db_next 数据库,您可以对其进行更改(使用 Management Studio 或 NHibernate 架构导出 或者 LinqToSql 创建数据库 或者其他的东西)。然后,您使用 _dev 和 _next 数据库执行迁移脚本生成器,这将创建。用于迁移的 SQL 更新脚本。

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

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

该工具自动化了下一个流程

  1. 对于每个数据库方案获取方案 ddls
  2. 将其置于版本控制之下

手动解决实例之间的更改

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top