代码之家  ›  专栏  ›  技术社区  ›  pix0r

跟踪数据库架构更改的机制[关闭]

  •  130
  • pix0r  · 技术社区  · 16 年前

    跟踪和/或自动化DB模式更改的最佳方法是什么?我们的团队使用Subversion进行版本控制,并且我们能够以这种方式自动化我们的一些任务(将构建推送到临时服务器,将测试代码部署到生产服务器),但是我们仍然手动进行数据库更新。我想找到或创建一个解决方案,使我们能够在不同环境的服务器之间高效地工作,同时继续使用Subversion作为后端,通过它代码和数据库更新被推送到不同的服务器上。

    许多流行的软件包包括自动更新脚本,用于检测数据库版本并应用必要的更改。这是在更大范围内(跨多个项目,有时是多个环境和语言)实现这一目标的最佳方法吗?如果是这样,是否有任何现有的代码可以简化流程,或者最好只是滚动我们自己的解决方案?是否有人以前实现过类似的东西并将其集成到SubversionPostCommit挂钩中,或者这是一个坏主意?

    虽然支持多个平台的解决方案更可取,但我们肯定需要支持linux/apache/mysql/php堆栈,因为我们的大部分工作都在该平台上。

    20 回复  |  直到 8 年前
        1
  •  55
  •   Andreas    8 年前

    在Rails世界中,有迁移的概念,在迁移脚本中,对数据库的更改是用Ruby而不是特定于数据库的SQL风格进行的。您的Ruby迁移代码最终被转换为当前数据库所特有的DDL;这使得切换数据库平台非常容易。

    对于对数据库所做的每一个更改,都要编写一个新的迁移。迁移通常有两种方法:应用更改的“向上”方法和撤消更改的“向下”方法。一个命令使数据库成为最新的,也可以用于使数据库成为模式的特定版本。在Rails中,迁移保存在项目目录中自己的目录中,并像其他项目代码一样签入版本控制。

    This Oracle guide to Rails migrations 很好地涵盖了迁移。

    使用其他语言的开发人员已经研究了迁移,并实现了自己的语言特定版本。我知道 Ruckusing 是一个在Rails迁移之后建模的PHP迁移系统;它可能是您正在寻找的。

        2
  •  48
  •   Dinah SLaks    11 年前

    我们使用类似于bcwood的东西来保持数据库模式在5个不同的安装(生产、分段和一些开发安装)之间保持同步,并在版本控制中进行备份,而且它工作得很好。我会详细说明一下:


    为了同步数据库结构,我们有一个脚本update.php,以及一些编号为1.sql、2.sql、3.sql等的文件。该脚本使用一个额外的表来存储数据库的当前版本号。n.sql文件是手工制作的,从数据库的版本(n-1)转到版本n。

    它们可以用于添加表、添加列、将数据从旧的列格式迁移到新的列格式,然后删除列、插入“主”数据行(如用户类型等)。基本上,它可以做任何事情,使用适当的数据迁移脚本,您将永远不会丢失数据。

    更新脚本的工作方式如下:

    • 连接到数据库。
    • 备份当前数据库(因为 出错[mysqldump]。
    • 如果不存在,创建簿记表(称为_meta)。
    • 从元表中读取当前版本。如果找不到,则假定为0。
    • 对于所有编号高于版本的.sql文件,按顺序执行
    • 如果其中一个文件产生错误:回滚到备份
    • 否则,将簿记表中的版本更新为执行的最高.sql文件。

    所有内容都进入源代码管理,每个安装都有一个脚本,用一个脚本执行更新到最新版本(使用正确的数据库密码调用update.php等)。我们通过一个自动调用数据库更新脚本的脚本来更新登台和生产环境,因此代码更新附带必要的数据库更新。

    我们也可以使用相同的脚本从头开始重新创建整个数据库;我们只需删除并重新创建数据库,然后运行将完全重新填充数据库的脚本。我们还可以使用该脚本填充一个空数据库以进行自动测试。


    建立这个系统只花了几个小时,从概念上讲很简单,每个人都得到了版本编号方案,而且它对于在不需要通信或手动执行对所有数据库的修改的情况下推进和改进数据库设计的能力是非常宝贵的。

    但是,在粘贴来自phpmyadmin的查询时要小心! 这些生成的查询通常包括数据库名称,您肯定不希望这样做,因为它会破坏您的脚本!比如创建表格 mydb . newtable (…)将失败,如果系统上的数据库不是调用mydb。我们创建了一个预注释SVN挂钩,它将禁止包含 MyDB 字符串,这是某人未经正确检查就从phpmyadmin复制/粘贴的肯定标志。

        3
  •  11
  •   Brandon Wood    16 年前

    我的团队编写所有数据库更改的脚本,并将这些脚本连同应用程序的每个版本提交给SVN。这允许对数据库进行增量更改,而不会丢失任何数据。

    要从一个版本切换到下一个版本,您只需要运行一组更改脚本,并且您的数据库是最新的,并且您仍然拥有所有的数据。这可能不是最简单的方法,但肯定是有效的。

        4
  •  9
  •   Nathan Rozentals    15 年前

    这里的问题确实使开发人员很容易将自己的本地更改脚本化为源代码管理,以便与团队共享。多年来,我一直面临着这个问题,并且受到了Visual Studio for Database专业人员功能的启发。如果您希望使用具有相同功能的开源工具,请尝试以下操作: http://dbsourcetools.codeplex.com/ 玩得高兴, -弥敦。

        5
  •  9
  •   Christophe Fondacci    14 年前

    如果您仍在寻找解决方案:我们正在提议一个名为nextep designer的工具。它是一个数据库开发环境,您可以使用它将整个数据库置于版本控制之下。您在一个版本控制的存储库中工作,在该存储库中可以跟踪每个更改。

    当需要发布更新时,可以提交组件,产品将自动从以前的版本生成SQL升级脚本。当然,您可以从任何2个版本生成这个SQL。

    然后,您有许多选择:您可以使用这些脚本,并将它们与应用程序代码一起放到SVN中,这样就可以通过现有的机制部署这些脚本。另一种选择是使用nextep的传递机制:脚本以“传递包”(SQL脚本+XML描述符)的形式导出,安装程序可以理解该包并将其部署到目标服务器,同时确保结构一致性、依赖性检查、注册已安装的版本等。

    该产品是GPL,基于Eclipse,因此可以在Linux、Mac和Windows上运行。目前,它还支持Oracle、MySQL和PostgreSQL(正在进行DB2支持)。看看wiki,你会发现更多的详细信息: http://www.nextep-softwares.com/wiki

        6
  •  6
  •   deadprogrammer    16 年前

    将架构转储到一个文件中,并将其添加到源代码管理中。然后一个简单的diff将向您显示更改的内容。

        7
  •  6
  •   Sam McAfee    16 年前

    Scott Ambler撰写了一系列伟大的文章 book )在数据库重构中,您应该基本上应用TDD原则和实践来维护您的模式。为数据库设置一系列结构和种子数据单元测试。然后,在您更改任何内容之前,您修改/编写测试以反映该更改。

    我们这样做已经有一段时间了,而且似乎是有效的。我们编写代码来在单元测试套件中生成基本的列名和数据类型检查。我们可以随时重新运行这些测试,以验证SVN签出中的数据库是否与应用程序实际运行的活动数据库匹配。

    事实证明,开发人员有时也会调整他们的沙盒数据库,忽略在SVN中更新模式文件。然后,代码取决于尚未签入的数据库更改。这种类型的bug可能非常难以确定,但测试套件会立即发现。如果您将它构建到一个更大的持续集成计划中,这就特别好。

        8
  •  5
  •   Mike Stone    16 年前

    这有点低技术,可能有更好的解决方案,但您可以将您的模式存储在一个可以运行以创建数据库的SQL脚本中。我认为您可以执行一个命令来生成这个脚本,但不幸的是,我不知道该命令。

    然后,将脚本连同处理它的代码提交到源代码管理中。当需要随代码一起更改架构时,可以将脚本与需要更改架构的代码一起签入。然后,脚本上的diff将指示模式更改上的diff。

    使用这个脚本,您可以将它与DBUnit或某种构建脚本集成,这样它似乎可以与您已经自动化的过程相适应。

        9
  •  5
  •   Dan TheCodeJunkie    16 年前

    如果您使用的是C,请看一看亚音速,这是一个非常有用的ORM工具,但是它也会生成SQL脚本来重新创建您的方案和/或数据。然后可以将这些脚本放入源代码管理中。

    http://subsonicproject.com/

        10
  •  5
  •   Rob aem    16 年前

    K.Scott Allen有一两篇关于模式版本化的文章,其中使用了这里其他答案中引用的增量更新脚本/迁移概念;请参阅 http://odetocode.com/Blogs/scott/archive/2008/01/31/11710.aspx .

        11
  •  4
  •   tbreffni    16 年前

    我在Visual Studio中为几个项目使用了以下数据库项目结构,并且效果非常好:

    数据库

    更改脚本

    预部署SQL

    1.架构更改.sql

    2.数据更改.sql

    3.权限.sql

    创建脚本

    链轮

    功能

    意见

    然后,我们的构建系统按照以下顺序执行脚本,将数据库从一个版本更新到下一个版本:

    1.预部署

    2.架构更改.sql

    创建脚本文件夹的内容

    2.数据更改.sql

    3.权限.sql

    每个开发人员通过将代码附加到每个文件的末尾来检查对特定bug/特性所做的更改。一旦主版本完成并分支到源代码管理中,将删除change scripts文件夹中.sql文件的内容。

        12
  •  4
  •   Satish Sharma    10 年前

    我们使用一个非常简单但有效的解决方案。

    对于新的安装,我们在存储库中有一个metadata.sql文件,它保存了所有的db模式,然后在构建过程中,我们使用这个文件来生成数据库。

    对于更新,我们将更新添加到硬编码软件中。我们对它进行了硬编码,因为我们不喜欢在问题真正成为问题之前解决问题,而且这种事情到目前为止还不是问题。

    所以在我们的软件中我们有这样的东西:

    RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

    此代码将检查数据库是否在版本1中(存储在自动创建的表中),如果数据库过期,则执行该命令。

    为了更新存储库中的metadata.sql,我们在本地运行此升级,然后提取完整的数据库元数据。

    唯一经常发生的事情是忘记提交metadata.sql,但这不是一个主要问题,因为它易于在构建过程中进行测试,而且唯一可能发生的事情是使用过时的数据库进行新安装,并在第一次使用时对其进行升级。

    此外,我们不支持降级,但从设计上讲,如果更新中出现问题,我们会还原以前的版本并在重试之前修复更新。

        13
  •  3
  •   Louis Salin    16 年前

    我创建以构建版本命名的文件夹,并在其中放置升级和降级脚本。例如,您可以拥有以下文件夹:1.0.0、1.0.1和1.0.2。每个脚本都包含允许您在不同版本之间升级或降级数据库的脚本。

    如果客户机或客户给您打电话时发现版本1.0.1有问题,而您使用的是1.0.2,那么将数据库恢复到其版本将不会有问题。

    在数据库中,创建一个名为“schema”的表,将其放入数据库的当前版本中。然后编写一个可以为您升级或降级数据库的程序很容易。

    就像乔伊说的,如果你在一个Rails的世界里,使用迁移。:)

        14
  •  2
  •   Eric Scrivner    16 年前

    对于我当前的PHP项目,我们使用了Rails迁移的思想,并且我们有一个迁移目录,其中保存文件标题“migration_xx.sql”,其中xx是迁移的数量。目前,这些文件是在进行更新时手动创建的,但是可以很容易地修改它们的创建。

    然后我们有一个名为“Migration_Watcher”的脚本,正如在pre-alpha中一样,它当前在每次页面加载时运行,并检查是否有一个新的migration_xx.sql文件,其中xx大于当前的迁移版本。如果是这样的话,它会运行所有的迁移文件,直到数据库和voila的最大数量!模式更改是自动的。

    如果您需要恢复系统的能力,则需要进行大量的调整,但这很简单,迄今为止我们的小团队一直工作得很好。

        15
  •  2
  •   Cruz    16 年前

    我建议在“脚本”方面使用Ant(跨平台)(因为它实际上可以通过JDBC与外面的任何数据库进行对话)并对源存储库进行Subversion。 在进行更改之前,Ant将允许您将数据库“备份”到本地文件。 1。通过Ant将现有的DB模式备份到文件 2。通过Ant对Subversion存储库的版本控制 三。通过Ant向数据库发送新的SQL语句

        16
  •  2
  •   Petah    13 年前

    toad for mysql有一个名为schema compare的函数,允许您同步2个数据库。这是迄今为止我使用的最好的工具。

        17
  •  2
  •   Edson Medina    13 年前

    imho迁移确实有一个巨大的问题:

    从一个版本升级到另一个版本是可行的,但是如果您有数百个表和很长的更改历史(如我们所做的),那么对给定版本进行新的安装可能永远都需要。

    从基线到当前版本(用于数百个客户数据库)运行Delta的整个历史可能需要很长时间。

        18
  •  2
  •   Ton van den Heuvel    13 年前

    我喜欢这种方式 Yii 处理数据库迁移。迁移基本上是一个PHP脚本实现 CDbMigration . CDB迁移 定义一个 up 包含迁移逻辑的方法。也可以实现 down 方法来支持迁移的反转。或者, safeUp safeDown 可用于确保在事务上下文中完成迁移。

    yii的命令行工具 yiic 包含创建和执行迁移的支持。迁移可以逐个应用或逆转,也可以成批应用或逆转。创建迁移会导致PHP类实现的代码 CDB迁移 ,根据用户指定的时间戳和迁移名称唯一命名。以前应用于数据库的所有迁移都存储在迁移表中。

    有关更多信息,请参阅 Database Migration 手册中的文章。

        19
  •  2
  •   cwash    12 年前
        20
  •  0
  •   stepancheg    15 年前

    有一个命令行 mysql-diff 用于比较数据库架构的工具,其中架构可以是活动数据库或磁盘上的SQL脚本。它适用于大多数模式迁移任务。