我觉得我的商店有一个漏洞,因为我们没有一个可靠的流程来版本化我们的数据库模式更改.我们做了很多备份,所以我们或多或少都被覆盖了,但以这种方式依赖你的最后一道防线是不好的做法.
令人惊讶的是,这似乎是一个共同点.我说过的很多商店都忽略了这个问题,因为他们的数据库并没有经常改变,而且他们基本上只是努力做到细致.
但是,我知道这个故事是怎么回事.事情排列错误只是一个时间问题而且缺少某些东西.
对此有什么最佳做法吗?有哪些策略对你有用?
必须阅读在版本控制下获取数据库.查看K. Scott Allen的一系列帖子.
在版本控制方面,数据库通常是第二类甚至是三等公民.从我所看到的情况来看,那些在一百万年内从未想过编写没有版本控制代码的团队 - 这是正确的 - 可能会完全忘记对应用程序所依赖的关键数据库进行版本控制的需求.我不知道当你的数据库与其他代码完全没有完全相同的源代码控制级别时,你怎么称自己为软件工程师并保持直面.不要让这件事发生在你身上.在版本控制下获取数据库.
数据库本身?没有
创建它们的脚本,包括静态数据插入,存储过程等; 当然.它们是文本文件,它们包含在项目中,并像其他一样检入和检出.
当然,在理想的世界中,您的数据库管理工具会这样做; 但你必须遵守纪律.
我非常喜欢Rails ActiveRecord迁移.它将DML抽象为ruby脚本,然后可以在源存储库中轻松进行版本化.
但是,通过一些工作,你可以做同样的事情.任何DDL更改(ALTER TABLE等)都可以存储在文本文件中.保留文件名的编号系统(或日期戳),并按顺序应用它们.
Rails在数据库中还有一个"版本"表,用于跟踪上次应用的迁移.你可以轻松地做同样的事情.
查看LiquiBase以使用源代码管理来管理数据库更改.
您永远不应该只是登录并开始输入"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
我确信有更好的方法可以做到这一点,但到目前为止它对我有用.
是.代码是代码.我的经验法则是,我需要能够从头开始构建和部署应用程序,而无需查看开发或生产机器.
我见过的最佳实践是创建一个构建脚本,以便在登台服务器上废弃和重建数据库.每次迭代都有一个用于数据库更改的文件夹,所有更改都使用"Drop ... Create"编写.这样,您可以随时将构建指向要版本的文件夹,从而回滚到早期版本.
我相信这是用NaNt/CruiseControl完成的.
是的,我认为对数据库进行版本控制非常重要.不是数据,而是某些模式.
在Ruby On Rails中,这由具有"迁移"的框架处理.每次更改数据库时,都会创建一个应用更改并将其检入源代码管理的脚本.
我的店铺非常喜欢这个想法,我们使用shell脚本和Ant 为基于Java的构建添加了这些功能.我们将流程集成到我们的部署例程中.编写脚本以在其他框架中执行相同的操作相当容易,这些框架不支持开箱即用的DB版本控制.
Visual Studio中的新数据库项目提供源代码控制和更改脚本.
他们有一个很好的工具来比较数据库,并且可以生成一个脚本,将一个模式转换为另一个,或者将数据更新为一个以匹配另一个.
db模式被"粉碎"以创建许多很小的.sql文件,每个DDL命令描述一个DB.
+汤姆
附加信息2008-11-30
在过去的一年里,我一直在使用它作为开发人员而且非常喜欢它.它可以轻松地将我的开发工作与生产进行比较,并生成用于发布的脚本.我不知道DBA是否缺少"企业级"项目所需的功能.
因为模式被"粉碎"成sql文件,所以源代码控制工作正常.
一个问题是,当您使用db项目时,您需要有不同的心态.该工具在VS中有一个"db项目",它只是sql,加上一个自动生成的本地数据库,它具有模式和一些其他管理数据 - 但是没有您的应用程序数据,还有您用于的本地dev db应用数据开发工作.你很少知道自动生成的数据库,但你必须知道它在那里,所以你可以不管它:).这个特殊的数据库清晰可辨,因为它的名字中有一个Guid,
VS DB项目可以很好地将其他团队成员进行的数据库更改集成到本地项目/关联数据库中.但您需要采取额外步骤将项目架构与本地dev db架构进行比较并应用mod.这很有道理,但一开始看起来很尴尬.
DB Projects是一个非常强大的工具.它们不仅可以生成脚本,还可以立即应用它们.一定不要用它来销毁你的生产数据库.;)
我非常喜欢VS DB项目,我希望将此工具用于我的所有数据库项目.
+汤姆
要求开发团队使用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/
我通过保存创建/更新脚本和生成采样数据的脚本来实现.
是的,我们通过将SQL作为构建的一部分来实现 - 我们保留DROP.sql,CREATE.sql,USERS.sql,VALUES.sql和版本控制这些,因此我们可以恢复到任何标记版本.
我们还有ant任务,可以在需要时重新创建db.
此外,SQL随后会与您的源代码一起被标记.
我在项目中使用过的最成功的方案是备份和差异SQL文件.基本上我们会在每次发布后备份我们的数据库并执行SQL转储,这样我们就可以从头开始创建一个空白模式.然后,只要您需要对DB进行更改,就可以在版本控制下的sql目录中添加alter scrip.我们总是将序列号或日期作为文件名的前缀,因此第一次更改将类似于01_add_created_on_column.sql,下一个脚本将是02_added_customers_index.我们的CI计算机将检查这些并按顺序在从备份还原的数据库的新副本上运行它们.
我们还有一些脚本可供devs使用单个命令将其本地db重新初始化为当前版本.
我们对所有dabase创建的对象进行源代码控制.只是为了让开发人员保持诚实(因为你可以在没有源代码控制的情况下创建对象),我们的dbas会定期查找不在源代码控制中的任何内容,如果他们发现任何内容,他们会在不询问是否正常的情况下删除它.
我使用SchemaBank来控制我所有的数据库架构更改:
从第1天开始,我将db模式转储导入其中
我开始使用Web浏览器更改我的架构设计(因为它们是基于SaaS /云的)
当我想更新我的数据库服务器时,我从它生成更改(SQL)脚本并应用于数据库.在Schemabank中,他们要求我在生成更新脚本之前将我的工作作为版本提交.我喜欢这种练习,这样我就可以随时追踪.
我们的团队规则是永远不要直接触摸数据库服务器而不先存储设计工作.但它发生了,为方便起见,有人可能会试图违反规则.我们会再次将模式转储导入到schemabank中,如果发现差异,就让它做差异并打击某人.虽然我们可以从中生成alter脚本以使我们的db和schema设计同步,但我们只是讨厌它.
顺便说一句,他们还允许我们在版本控制树中创建分支,以便我可以维护一个用于分段,一个用于生产.还有一个用于编码沙箱.
一个非常简洁的基于Web的架构设计工具,具有版本控制和变更管理.