您是否对数据库项目使用源代码管理?[关闭]


596

我觉得我的店有个漏洞,因为我们没有适当的过程来版本化数据库架构更改。我们进行了大量备份,因此我们或多或少都得到了保障,但是以这种方式依赖您的最后一道防线是不明智的做法。

令人惊讶的是,这似乎是一个常见的话题。我说过的许多商店都忽略了这个问题,因为它们的数据库不经常更改,并且基本上只是在尝试细致。

但是,我知道那个故事是怎么回事。事情排错了一切,丢失了东西只是时间问题。

是否有最佳做法?有哪些对您有用的策略?


在Podcast 54的结尾处进行了讨论。blog.stackoverflow.com/2009/05
Chris Moschini

Answers:


387

必须阅读使数据库受版本控制。查看K. Scott Allen的系列文章。

在版本控制方面,数据库通常是二等甚至三等公民。从我所看到的情况来看,在一百万年之内不会考虑没有版本控制的情况下编写代码的团队-的确如此-可以完全忽略应用程序所依赖的关键数据库的版本控制需求。我不知道当数据库未与其余代码完全处于相同的严格源代码控制级别时,如何称呼自己为软件工程师并保持直言不讳。不要让这种情况发生在您身上。使数据库受版本控制。


1
我非常仔细地遵循引用的文章中描述的方法。您不需要实现每个级别,并且有一些变体同样可以很好地起作用。该系统灵活,易于定制,可以对模式和数据更改进行细粒度控制,并且可以很好地用作数据库源代码控制的最佳实践。该部分可能很棘手,并且几乎与其余过程一样增加了安全性,是帮助管理脚本的工具。它可以像文件串联一样简单,也可以像自动化部署一样复杂。首先获取src ctrl,然后考虑一个工具。
ulty4life

1
有一个名为Klonio的分布式数据库版本控制系统,类似于数据库的Git / GitHub。
Augiwan 2015年

134

数据库本身?没有

创建它们的脚本,包括静态数据插入,存储过程等;当然。它们是文本文件,它们包含在项目中,并且像其他所有文件一样签入和签出。

当然,在理想情况下,您的数据库管理工具可以做到这一点。但您只需要对此加以纪律。


7
使用Mysql Workbench,您可以将所有内容保存在可以用GUI打开和处理的结构化文件(xml)中。由于xml仅是文本,是的,无需键入单个sql语句即可进行版本控制。
levhita

6
数据库本身正是需要在源代码控制之下的数据库,因为否则,这是手动回滚/有选择地应用模式更改以匹配您的代码库分支的手动过程。如果我有三个从属项目,并且将它们全部切换到一个特定的分支(例如,具有一组特定的架构迁移),那么我也应该能够将我的数据库也切换到该架构。同样,它应支持合并和变基操作。严重缺乏这项技术。在进行数据库迁移时,实体框架不支持多开发人员环境。
Triynko

@Triynko在实践中不起作用。微软为什么要取消他们的数据库项目Visual Studio类型3次以上是有原因的。这是因为知道源模式和目标模式会丢失有关模式迁移的所有信息。如果重构架构,则会浪费大量信息。我们放弃了使用该模型的尝试,而是使用精心设计为可重新运行等状态容忍度的增量迁移脚本。
希夫

我会注意到Shiv和Tryinko的讨论通常被定义为“基于状态”与“基于迁移”。这是一个颇具争议的问题,两种方法各有利弊。我将注意到,基于迁移的方法往往可以更快地创建/替换/更新具有最新迁移的数据库,而基于状态的方法则可以实际创建更改。哪种方法更好,部分取决于您是否要优先进行频繁的数据库更改(基于状态)或对生产/测试/本地/ CI进行频繁的部署(基于迁移)。
布莱恩(Brian)

关于Microsoft为什么要使用基于状态的方法的原因:为基于状态的方法构建工具/自动化要容易得多,并且对开发人员来说交钥匙得多。当前不对数据库使用版本控制的开发人员通常会发现基于状态的方法更具吸引力,因为它的破坏性较小。当然,其破坏性较小的原因是,将迁移工作从开发人员推送到了发布工程师...他们将生成差异脚本(例如,通过SSDT),然后手动进行修复,希望他们不会错过任何东西。
布莱恩(Brian)

36

我绝对喜欢Rails ActiveRecord迁移。它将DML抽象为ruby脚本,然后可以在源存储库中轻松对其进行版本控制。

但是,通过一些工作,您可以做同样的事情。任何DDL更改(ALTER TABLE等)都可以存储在文本文件中。为文件名保留编号系统(或日期戳),并依次应用它们。

Rails在数据库中也有一个“版本”表,用于跟踪上一次应用的迁移。您可以轻松地执行相同操作。


1
完全同意,当前迁移版本绑定到当前提交,因此您可以运行rake任务,并通过更改数据库来保持系统清洁和简单的过程
Anatoly


29

您永远不应仅登录并开始输入“ ALTER TABLE”命令来更改生产数据库。我所在的项目在每个客户站点上都有数据库,因此对数据库的每次更改都在两个地方进行,一个用于在新客户站点上创建新数据库的转储文件,以及一个正在运行的更新文件每次更新时,都会根据文件中的最高编号检查当前数据库版本号,并就地更新数据库。因此,例如,最后几个更新:

if [ $VERSION \< '8.0.108' ] ; then
  psql -U cosuser $dbName << EOF8.0.108
    BEGIN TRANSACTION;
    --
    -- Remove foreign key that shouldn't have been there.
    -- PCR:35665
    --
    ALTER TABLE     migratorjobitems
    DROP CONSTRAINT migratorjobitems_destcmaid_fkey;
    -- 
    -- Increment the version
    UPDATE          sys_info
    SET             value = '8.0.108'
    WHERE           key = 'DB VERSION';
    END TRANSACTION;
EOF8.0.108
fi

if [ $VERSION \< '8.0.109' ] ; then
  psql -U cosuser $dbName << EOF8.0.109
    BEGIN TRANSACTION;
    --
    -- I missed a couple of cases when I changed the legacy playlist
    -- from reporting showplaylistidnum to playlistidnum
    --
    ALTER TABLE     featureidrequestkdcs
    DROP CONSTRAINT featureidrequestkdcs_cosfeatureid_fkey;
    ALTER TABLE     featureidrequestkdcs
    ADD CONSTRAINT  featureidrequestkdcs_cosfeatureid_fkey
    FOREIGN KEY     (cosfeatureid)
    REFERENCES      playlist(playlistidnum)
    ON DELETE       CASCADE;
    --
    ALTER TABLE     ticket_system_ids
    DROP CONSTRAINT ticket_system_ids_showplaylistidnum_fkey;
    ALTER TABLE     ticket_system_ids
    RENAME          showplaylistidnum
    TO              playlistidnum;
    ALTER TABLE     ticket_system_ids
    ADD CONSTRAINT  ticket_system_ids_playlistidnum_fkey
    FOREIGN KEY     (playlistidnum)
    REFERENCES      playlist(playlistidnum)
    ON DELETE       CASCADE;
    -- 
    -- Increment the version
    UPDATE          sys_info
    SET             value = '8.0.109'
    WHERE           key = 'DB VERSION';
    END TRANSACTION;
EOF8.0.109
fi

我敢肯定有更好的方法可以做到这一点,但是到目前为止,它对我来说是有效的。


除了将每个“ if版本”放在单独的文件中并有一个按顺序运行文件的工具外,我们执行类似的操作。
jwanagel

除了安装了SQL脚本(新安装或升级)以及应用文件,并记录了脚本执行的位置,日期和时间之外,我们还在做类似的事情。
si618

我也写了几乎完全像这样的内容,但是对于Jet(例如MS Access)数据库。我们当前正在使用DB Ghost for SQL Server,它可以为您完成很多工作。
肯尼·埃维特

您可以替换begin transaction; ... end transaction;为传递--single-transactionpsql
弗拉基米尔

18

是。代码就是代码。我的经验法则是,我需要能够从头开始构建和部署应用程序,而无需查看开发或生产机器。


13

我看到的最佳实践是创建一个构建脚本,以在临时服务器上剪贴和重建数据库。每次迭代都有一个用于数据库更改的文件夹,所有更改都使用“ Drop ... Create”的脚本编写。通过这种方式,您可以随时通过将构建指向要版本控制的文件夹来回滚到早期版本。

我相信这是通过NaNt / CruiseControl完成的。


11

是的,我认为对数据库进行版本控制很重要。不是数据,而是确定的架构。

在Ruby On Rails中,这由带有“迁移”的框架来处理。每次更改数据库时,都将创建一个脚本来应用更改并将其检入源代码管理。

我的商店非常喜欢这个主意,因此我们使用Shell脚本和Ant 将功能添加到了基于Java的构建中。我们将流程集成到了我们的部署例程中。编写脚本以在不支持即用型数据库版本控制的其他框架中执行相同的操作将是相当容易的。


8

Visual Studio中的新数据库项目提供了源代码管理和更改脚本。

他们有一个比较数据库的好工具,可以生成一个脚本,将一个模式转换为另一个模式,或更新一个模式中的数据以匹配另一个模式。

db模式被“切碎”以创建许多非常小的.sql文件,每个描述数据库的DDL命令一个。

+汤姆


附加信息2008-11-30

在过去的一年中,我一直将其用作开发人员,并且非常喜欢它。可以轻松地将我的开发工作与生产进行比较,并生成用于发布的脚本。我不知道它是否缺少DBA“企业型”项目所需的功能。

因为该架构已“切碎”到sql文件中,所以源代码控件可以正常工作。

一个陷阱是,使用数据库项目时,您需要有不同的心态。该工具在VS中有一个“数据库项目”,它只是sql,还有一个自动生成的本地数据库,该数据库具有架构和一些其他管理数据-但没有您的应用程序数据,还有用于该数据库的本地dev db应用数据开发工作。您很少知道自动生成的数据库,但是您必须在那里知道它,因此您可以不理会它:)。可以清楚地识别出这个特殊的数据库,因为它的名称中包含一个Guid,

VS DB项目在将其他团队成员所做的数据库更改集成到本地项目/相关数据库方面做得很好。但您需要采取额外的步骤来将项目架构与本地dev db架构进行比较,并应用mod。这是有道理的,但起初似乎很尴尬。

数据库项目是一个非常强大的工具。它们不仅生成脚本,而且可以立即应用它们。确保不要破坏它的生产数据库。;)

我真的很喜欢VS DB项目,并且我希望以后的所有数据库项目都可以使用此工具。

+汤姆


8

要求开发团队使用SQL数据库源代码管理管理系统并不是解决问题的灵丹妙药。由于开发人员需要将对对象所做的更改保存在单独的SQL脚本中,打开源代码管理系统客户端,使用客户端检入SQL脚本文件,然后,数据库源控件本身会带来额外的开销。将更改应用到实时数据库。

我可以建议使用称为ApexSQL Source Control的SSMS加载项。它使开发人员可以直接通过SSMS的向导通过源控制系统轻松映射数据库对象。该插件包括对TFS,Git,Subversion和其他SC系统的支持。它还包括对源代码控制静态数据的支持。

下载并安装ApexSQL Source Control之后,只需右键单击要版本控制的数据库,然后导航到SSMS中的ApexSQL Source Control子菜单。单击将数据库链接到源代码管理选项,选择源代码管理系统和开发模型。之后,您需要提供所选信息源控制系统的登录信息和存储库字符串。

您可以阅读本文以获取更多信息:http : //solutioncenter.apexsql.com/sql-source-control-reduce-database-development-time/


6

我通过保存创建/更新脚本和生成样本数据的脚本来完成。


6

是的,我们通过将SQL保留在构建中来做到这一点-我们保留DROP.sql,CREATE.sql,USERS.sql,VALUES.sql并由版本控制这些,因此我们可以还原到任何带标记的版本。

我们还有一些ant任务,可以在需要时重新创建数据库。

另外,SQL随同您的源代码一起被标记。


6

我在项目上使用过的最成功的方案是将备份和差异SQL文件结合在一起。基本上,在每个发行版之后,我们都会备份数据库,并执行SQL转储,以便我们也可以从头开始创建空白模式。然后,每当需要更改数据库时,都可以在版本控制下向SQL目录中添加更改脚本。我们将始终在文件名前添加序列号或日期,因此第一个更改将类似于01_add_created_on_column.sql,下一个脚本将为02_added_customers_index。我们的CI机器将检查这些内容,并在已从备份还原的db的新副本上顺序运行它们。

我们还提供了一些脚本,开发人员可以使用这些脚本通过一个命令将其本地数据库重新初始化为当前版本。


6

我们对所有由dabase创建的对象进行源代码控制。只是为了使开发人员诚实(因为您可以创建对象而无需将其置于Source Control中),我们的dbas会定期查找不在Source Control中的任何内容,如果发现任何内容,他们会丢弃它而不询问是否可以。


5

我使用SchemaBank来版本控制所有数据库架构更改:

  • 从第一天开始,我将数据库模式转储导入到其中
  • 我开始使用Web浏览器更改架构设计(因为它们是基于SaaS /基于云的)
  • 当我想更新数据库服务器时,我从中生成更改(SQL)脚本并应用于数据库。在Schemabank中,他们要求我在生成更新脚本之前将我的工作提交为一个版本。我喜欢这种练习,因此我随时可以回溯。

我们的团队规则是永远不要直接触摸数据库服务器,而无需先存储设计工作。但是它的确发生了,为了方便起见,有人可能会想违反规则。我们将模式转储再次导入到schemabank中,让它进行比较,如果发现差异,则对某人进行打击。尽管我们可以从中生成alter脚本,以使数据库和架构设计同步,但我们对此感到讨厌。

顺便说一句,它们还允许我们在版本控制树中创建分支,以便我可以维护一个用于登台,一个用于生产。还有一个用于编码沙箱。

一个非常简洁的基于Web的架构设计工具,具有版本控制和变更管理功能。


4

我拥有从裸机重新创建数据库所需的一切,减去数据本身。我敢肯定有很多方法可以做到这一点,但是我所有的脚本等都存储在Subversion中,我们可以通过从Subversion中提取所有内容并运行安装程序来重建数据库结构。


4

我通常会为所做的每个更改构建一个SQL脚本,并为还原所做的更改构建一个SQL脚本,并将这些脚本置于版本控制之下。

然后,我们可以根据需要创建新的最新数据库,并且可以轻松地在修订之间移动。每次发布时,我们都会将脚本合并在一起(需要一些手动工作,但实际上很难),因此我们还有一组可以在版本之间转换的脚本。

是的,在您说出来之前,这与Rails和其他人所做的非常相似,但是它似乎运行得很好,因此我毫不客气地承认我无耻地提出了这个想法:)


4

我使用从MySQL Workbech导出的SQL CREATE脚本,然后使用它们的“导出SQL ALTER”功能,最后得到一系列创建脚本(当然编号)以及可以在它们之间应用更改的alter脚本。

3.-导出SQL ALTER脚本通常,您现在必须手动编写ALTER TABLE语句,以反映对模型所做的更改。但是您可以变得聪明,让Workbench为您完成艰苦的工作。只需从主菜单中选择File-> Export-> Forward Engineer SQL ALTER Script…。

这将提示您指定当前模型应与之比较的SQL CREATE文件。

从步骤1中选择SQL CREATE脚本。然后,该工具将为您生成ALTER TABLE脚本,您可以对数据库执行此脚本以使其更新。

您可以使用MySQL查询浏览器或mysql客户端执行此操作。您的模型和数据库现已同步!

来源:MySQL Workbench社区版:模式同步指南

当然,所有这些脚本都在版本控制下。


4

是的,总是。您应该能够在需要时使用一组有用的样本数据来重新创建生产数据库结构。如果不这样做,随着时间的流逝,为了保持运行正常而进行的微小更改就被遗忘了,那么有一天,您会被咬得很长。您可能不认为需要它的保险,但是当您这样做的时候,它的价值就值得超过10倍!


4

关于数据库模型本身已经进行了很多讨论,但是我们还将所需的数据保存在.SQL文件中。

例如,为了有用,您的应用程序可能需要在安装中进行以下操作:

INSERT INTO Currency (CurrencyCode, CurrencyName) 
VALUES ('AUD', 'Australian Dollars');

INSERT INTO Currency (CurrencyCode, CurrencyName) 
VALUES ('USD', 'US Dollars');

我们将currency.sql在subversion下有一个名为的文件。作为构建过程中的手动步骤,我们将先前的currency.sql与最新的currency.sql进行比较,并编写一个升级脚本。


我们将所需的数据保存在一个数据库中(谁会被打乱?),然后使用我们的工具生成这些插入/更新脚本,以使参考数据在dev,qa,production等之间保持同步。数据和以这种方式进行的更改。这些脚本全部由我们的版本/配置工具控制。
卡伦·洛佩兹

当数据库具有数百万行时,这是否可行?
罗尼

4

我们对数据库周围的所有内容进行版本控制和源代码控制:

  • DDL(创建和更改)
  • DML(参考数据,代码等)
  • 数据模型更改(使用ERwin或ER / Studio)
  • 数据库配置更改(权限,安全对象,常规配置更改)

我们使用变更管理器和一些自定义脚本通过自动化作业来完成所有这些工作。我们让变更管理器监视这些变更并通知完成的时间。


4

我相信每个数据库都应该受到源代码控制,并且开发人员应该有一种简便的方法来从头开始创建本地数据库。受Visual Studio for Database Professionals的启发,我创建了一个开放源代码工具,该工具可对MS SQL数据库进行脚本编写,并提供了一种将其部署到本地DB引擎的简便方法。尝试http://dbsourcetools.codeplex.com/。玩得开心,-内森。


4

如果您的数据库是SQL Server,我们可能只是您要寻找的解决方案。SQL Source Control 1.0现在已经发布。

http://www.red-gate.com/products/SQL_Source_Control/index.htm

这集成到SSMS中,并提供了数据库对象和VCS之间的粘合。“脚本输出”是透明进行的(它在后台使用了SQL Compare引擎),这应该使其使用起来如此简单,以至于不会妨碍开发人员采用该过程。

另一种Visual Studio解决方案是ReadyRoll,它作为SSDT数据库项目的子类型实现。这采用了迁移驱动的方法,该方法更适合DevOps团队的自动化要求。


我不会向任何人推荐Red-Gate的产品。我已经使用SQL Source Control 2.2一段时间了。实际上,他们很快发布了版本3。此后,他们结束了对2.2的任何支持。甚至他们都没有修复任何错误(我不认为新功能-缺陷是错误),它们还没有在TFS2012发布时不支持它。我的公司从TFS2010切换到TFS2012,我们再也无法连接到TFS。实际上,我们不得不丢弃Red Gate的软件,因为他们给我们的唯一选择是购买其软件的新版本。没有计划更新版本。2.2。
迪马

希望他们对非Microsoft操作系统具有CLI支持。
l8nite

看起来他们为MySQL提供了几个工具red-gate.com/products/mysql/mysql-comparison-bundle
Jeff

3

我通过编写所有对象(表定义,索引,存储过程等)的脚本来控制数据库模式。但是,对于数据本身,仅依赖常规备份。这样可以确保使用适当的修订历史记录捕获所有结构更改,但不会在每次数据更改时都对数据库造成负担。


3

在我们的业务中,我们使用数据库更改脚本。运行脚本时,它的名称存储在数据库中,并且不会再次运行,除非删除该行。脚本是根据日期,时间和代码分支命名的,因此可以执行受控。

在实时环境中运行脚本之前,需要进行大量测试,因此,通常情况下,“麻烦”仅发生在开发数据库上。


3

我们正在将所有数据库移至源代码管理。我们正在使用sqlcompare编写数据库脚本(不幸的是,该版本是专业版功能),并将该结果放入SVN中。

实施的成功将在很大程度上取决于组织的文化和实践。这里的人们相信为每个应用程序创建一个数据库。大多数应用程序都使用一组通用的数据库,这也会导致很多数据库间的依赖关系(其中一些是循环的)。由于我们的系统具有数据库间的依赖性,因此将数据库模式放入源代码管理非常困难。

祝您好运,您越早尝试一下,越早解决问题。



3

这对我来说也一直是一个很大的烦恼-似乎对开发数据库进行快速更改,将其保存(忘记保存更改脚本)太简单了,然后就陷入了困境。您可以撤消刚刚做的事情,然后重做以创建更改脚本,或者当然也可以从头开始编写它,尽管这花费了大量时间来编写脚本。

我过去使用过的有助于此功能的工具是SQL Delta。它将向您显示两个数据库(我相信是SQL Server / Oracle)之间的差异,并生成迁移A-> B所需的所有更改脚本。这样做的另一个好处是,可以显示生产(或测试)数据库与开发数据库之间的数据库内容之间的所有差异。由于越来越多的应用程序将对它们的执行至关重要的配置和状态存储在数据库表中,因此拥有删除,添加和更改适当行的更改脚本可能会非常痛苦。SQL Delta显示数据库中的行,就像它们在Diff工具中一样-更改,添加,删除。

出色的工具。这是链接:http : //www.sqldelta.com/


3

RedGate很棒,我们在进行数据库更改时会生成新的快照(一个很小的二进制文件),并将该文件作为资源保留在项目中。每当我们需要更新数据库时,我们都会使用RedGate的工具包来更新数据库,并能够从空数据库中创建新数据库。

RedGate还可以制作数据快照,尽管我还没有亲自使用过它们,但它们同样强大。


Red Gate的SQL Source Control是为解决此问题而开发的,因此请看一看,让我们知道它是否满足您的要求。与SQL Compare相比,SQL Source Control的优势在于它与SSMS集成在一起,因此不需要加载单独的工具来记录不同的架构版本。[我是Red Gate的产品经理]
David Atkinson,2010年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.