提问



我觉得我的商店有一个漏洞,因为我们没有一个可靠的流程来版本化我们的数据库模式更改。我们做了很多备份,所以我们或多或少地覆盖了,但依靠它是不好的做法你这样做的最后一道防线。


令人惊讶的是,这似乎是一个共同点。我说过的很多商店都忽略了这个问题,因为他们的数据库不经常改变,他们基本上只是努力做到细致。


但是,我知道这个故事是怎么回事。事情排列错误只是一个时间问题而且缺少某些东西。


对此有什么最佳做法吗?有哪些策略对你有用?

最佳参考


必须阅读在版本控制下获取数据库。查看K. Scott Allen的一系列帖子。[4]



  在版本控制方面,数据库通常是第二类甚至是三等公民。从我所看到的情况来看,那些在没有版本控制的情况下永远不会想到编写代码的团队在一百万年内 - 这是正确的 - 可能会完全忘记对应用程序依赖的关键数据库进行版本控制的需求。当你的数据库没有与其他代码完全相同的源代码控制级别时,你不知道如何称自己为软件工程师并保持直面。不要让这件事发生在你身上。在版本控制下获取数据库。


其它参考1


数据库本身?没有


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


当然,在理想的世界中,您的数据库管理工具会这样做;但你必须遵守纪律。

其它参考2


我非常喜欢Rails ActiveRecord迁移。它将DML抽象为ruby脚本,然后可以在源代码库中轻松地进行版本化。


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


Rails在数据库中还有一个版本表,用于跟踪上次应用的迁移。你可以轻松地做同样的事情。

其它参考3


查看LiquiBase以使用源代码管理来管理数据库更改。[5]

其它参考4


您永远不应该只是登录并开始输入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


我确信有更好的方法可以做到这一点,但到目前为止它对我有用。

其它参考5


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

其它参考6


我见过的最佳实践是创建一个构建脚本,以便在登台服务器上废弃和重建数据库。每次迭代都有一个用于数据库更改的文件夹,所有更改都使用Drop ... Create编写脚本。这样,您可以随时通过将构建指向要版本的文件夹来回滚到早期版本。


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

其它参考7


是的,我认为对您的数据库进行版本控制非常重要。不是数据,而是某些模式。


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


我的店铺非常喜欢这个想法,我们使用shell脚本和Ant为基于Java的构建添加了这些功能。我们将流程集成到我们的部署例程中。编写脚本以在其他不支持数据库版本开箱即用的框架中执行相同的操作相当容易。

其它参考8


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


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


db模式被粉碎以创建许多小的.sql文件,每个DDL命令描述一个DB。


+汤姆





附加信息2008-11-30


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


因为模式被粉碎成sql文件,所以源代码控制工作正常。


一个问题是,当您使用数据库项目时,您需要有不同的心态。该工具在VS中有一个db项目,它只是sql,加上一个自动生成的本地数据库,它具有模式和一些其他管理数据 - 但是没有你的应用程序数据,还有你用于的本地dev db应用数据开发工作。你很少知道自动生成的数据库,但你必须知道它在那里,所以你可以不管它:)。这个特殊的数据库清晰可辨,因为它的名字中有一个Guid,


VS DB项目可以很好地将其他团队成员进行的数据库更改集成到本地项目/关联数据库中。但您需要采取额外步骤将项目架构与本地dev db架构进行比较并应用mod。这很有意义,但一开始看起来很尴尬。


DB Projects是一个非常强大的工具。它们不仅可以生成脚本,还可以立即应用它们。一定不要用它来销毁你的生产数据库。 ;)


我非常喜欢VS DB项目,我希望将此工具用于我的所有数据库项目。


+汤姆

其它参考9


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


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


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


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

其它参考10


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

其它参考11


是的,我们通过将SQL作为构建的一部分来实现 - 我们保留DROP.sql,CREATE.sql,USERS.sql,VALUES.sql和版本控制这些,因此我们可以恢复到任何标记版本。


我们还有ant任务,可以在需要时重新创建db。


此外,SQL随后会与您的源代码一起被标记。

其它参考12


我们对所有dabase创建的对象进行源代码控制。只是为了让开发人员保持诚实(因为你可以在没有源代码控制的情况下创建对象),我们的dbas会定期查找不在源代码控制中的任何内容,如果他们发现任何内容,他们会在不询问是否正常的情况下删除它。

其它参考13


我在项目中使用过的最成功的方案是将备份和差异SQL文件结合起来。基本上我们会在每次发布后对db进行备份并进行SQL转储,以便我们可以从头开始创建一个空白模式当你需要对数据库进行更改时,你需要在版本控制下向sql目录添加一个alter scrip。我们总是在序列号或日期前加上文件名,所以第一次改变就像是01_add_created_on_column.sql,下一个脚本将是02_added_customers_index。我们的CI机器会检查这些并按顺序在从备份恢复的数据库的新副本上运行它们。


我们还有一些脚本可供devs使用单个命令将其本地db重新初始化为当前版本。

其它参考14


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

其它参考15


我通常为每个更改构建一个SQL脚本,另一个用于还原这些更改,并将这些脚本保留在版本控制之下。


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


是的,在你说之前,这与Rails和其他人的东西非常相似,但它看起来效果很好,所以我没有任何问题,承认我无耻地解除了这个想法:)

其它参考16


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



  3.-导出SQL ALTER脚本
  通常,您现在必须手动编写ALTER TABLE语句,以反映您对模型所做的更改。但是你可以聪明,让Workbench为你努力工作。只需从主菜单中选择文件 - >导出 - >转发工程师SQL ALTER脚本....

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

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

  
  你可以使用MySQL Query Browser或mysql client.Voila来做到这一点!您的模型和数据库现已同步!



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


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

其它参考17


是的,总是。您应该能够在需要时使用一组有用的示例数据重新创建生产数据库结构。如果你不这样做,随着时间的推移,一些细微的变化让事情变得容易被遗忘,那么有一天你会感到被咬,很大的时间。它保险你可能认为不需要,但是你做它的那天它价值10倍!

其它参考18


关于数据库模型本身已有很多讨论,但我们也将所需的数据保存在.SQL文件中。


例如,为了有用,您的应用程序可能需要在安装中使用它:


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

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


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

其它参考19


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



  • DDL(创建并改变)

  • DML(参考数据,代码等)

  • 数据模型更改(使用ERwin或ER/Studio)

  • 数据库配置更改(权限,安全对象,常规配置更改)



我们使用Change Manager和一些自定义脚本完成所有这些操作。我们让Change Manager监控这些更改并通知它们何时完成。

其它参考20


我相信每个数据库都应该受源代码控制,开发人员应该有一个简单的方法从头开始创建他们的本地数据库。受Visual Studio for Database Professionals的启发,我创建了一个脚本MS SQL数据库的开源工具,并提供了将它们部署到本地数据库引擎的简便方法。请尝试http://dbsourcetools.codeplex.com/。乐趣,
- 内森。[10]

其它参考21


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


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


它集成到SSMS中,并提供数据库对象和VCS之间的粘合。 脚本输出是透明地发生的(它使用了引擎盖下的SQL Compare引擎),这应该使得它非常简单易用,开发人员不会因为采用这个过程而感到沮丧。


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

其它参考22


我使用SchemaBank来控制我所有的数据库模式更改:[13]



  • 从第1天起,我将db模式转储导入其中

  • 我开始使用网络浏览器更改我的架构设计(因为它们是基于SaaS/云的)

  • 当我想更新我的数据库服务器时,我从中生成更改(SQL)脚本并应用于数据库。在Schemabank中,他们要求我在生成更新脚本之前将我的工作作为版本提交。我喜欢这种练习,这样我就可以在需要时随时追溯。



我们的团队规则是不要直接触摸数据库服务器而不先存储设计工作。但它发生了,为方便起见,有人可能会试图违反规则。我们会再次将模式转储导入到模式库中,如果发现差异,就让它进行差异并对某人进行重击。虽然我们可以从中生成alter脚本以使我们的db和schema设计同步,但我们只是讨厌它。


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


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

其它参考23


我通过脚本化所有对象(表定义,索引,存储过程等)来控制数据库模式。但是,至于数据本身,只需依靠定期备份。这确保了使用适当的修订历史记录捕获所有结构更改,但每次数据更改时都不会给数据库带来负担。

其它参考24


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


在脚本在实时环境中运行之前完成了大量的测试,因此oopsies只会在开发数据库上发生。

其它参考25


我们正在将所有数据库移动到源代码控制。我们正在使用sqlcompare编写数据库脚本(不幸的是专业版功能)并将结果放入SVN。


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


祝你好运,越早尝试,你就越早解决问题。

其它参考26


我在http://dbdeploy.com/上使用了ThoughtWorks的dbdeploy工具。它鼓励使用迁移脚本。每个版本,我们将更改脚本合并到一个文件中,以便于理解并允许DBA祝福更改。[14]

其它参考27


这对我来说一直是一个很大的烦恼 - 似乎很容易快速更改你的开发数据库,​​保存(忘记保存更改脚本),然后你卡住了。你可以撤消你刚才所做的事情并重做它来创建更改脚本,或者如果你当然也想从头开始编写它,尽管编写脚本花了很多时间。


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


一个很好的工具。链接在这里:
http://www.sqldelta.com/[15]

其它参考28


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


RedGate也制作了数据快照,而我个人并没有与他们合作,他们也同样强大。

其它参考29


仅供参考我几天前由Dana提出......源代码控制中的存储过程/数据库模式