ede*_*rbf 14 sql sql-server version-control sql-server-2008
我是一个开发团队的一员,目前正在使用一个没有任何源代码控制的数据库.我们使用SQL Server 2008 R2并始终使用SSMS直接管理数据库.它现在有~340个表和~1600个存储过程,加上一些触发器和视图,因此它不是一个小型DB.
我的目标是让数据库处于版本控制之下,所以我一直在阅读文章,比如Scott Allen的系列文章和许多旧的SO相关问题.但我仍然无法决定如何继续.
我在想的是将数据库模式编写在一个文件中,然后在每个文件中编写过程,触发器和视图.然后将所有版本都保存在Mercurial下.但是,当然,团队的每个成员都可以访问SSMS并直接更改模式和过程,我们任何人都可能忘记在版本化文件中复制这些更改.
还有哪些更好的选择?而且,我是否忘记了任何值得拥有源代码控制权的元素?我最关心的是,我发现的大多数文献都解释了在创建新数据库时如何进行版本控制,但是当它已经陈旧并且相对较大时.
Hac*_*ese 14
一般过程
我们为特定版本创建基线(比方说v1.0).基线包括一个完整的模式创建脚本,以及来自允许的先前版本的升级脚本(如果有的话)(稍后会详细介绍).因此v1.0,我们只有一个脚本:
baseline-v1.0.sql
Run Code Online (Sandbox Code Playgroud)
从该基线开始,我们在从前一个基线开始工作时创建增量更改脚本.这些脚本以可重入的方式创建,以便它们可以安全地多次运行(第一次只执行任何实际工作;请参阅下一段有关建议的方法).我们只是为每个更改脚本创建一个文件,其中包含基线名称和时间戳(我们称之为版本).例如,假设我们在基线之后创建了两个更改脚本.我们有以下文件:
baseline-v1.0.sql (for creating new installations)
baseline-v1.0-201211071220.sql (created on Nov. 7, 2012 at 12:20 PM UTC)
baseline-v1.0-201211122019.sql (created on Nov. 12, 2012 at 8:00 PM UTC)
Run Code Online (Sandbox Code Playgroud)
我们创建一个schema_version包含两列的表:baseline和version.baseline是一些标签(v1.0如上所述),version它只是创建更改脚本的时间戳(我们选择这样做是因为创建任意版本号会产生令人讨厌的管理开销,其中时间戳很容易使用).因此,在运行更改脚本之前,我们检查是否已经应用了更改脚本,方法是通过baseline和查询它version.如果它已经存在,只需退出脚本或其他任何内容.否则,应用更改并插入schema_version表中以标记已完成的更改脚本.
示例更改脚本:
-- Created by <developer> on Nov. 7, 2012 at 12:20 PM UTC
declare @schema_baseline varchar(10), @schema_version varchar(12)
set @schema_baseline = 'v1.0'
set @schema_version = '201211071210'
if exists (select 1 from schema_version where baseline = @schema_baseline and version = @schema_version = @schema_version) return 0
-- begin change script
-- place your schema changes here
-- end change script
insert into schema_version(@schema_baseline, @schema_version)
Run Code Online (Sandbox Code Playgroud)
现在,当我们实际安装软件时,我们运行相关的baseline脚本.在我们升级该版本时,我们只是按顺序应用更改脚本.
当我们在产品开发阶段达到一个重要的里程碑时,我们会创建一个新的基线.因此,我们创建了一个新的基线脚本(同样,这是数据库作为基线的快照),以及上一个基线的升级脚本.所以假设我们有一个新的基线v2.0,我们有以下文件:
baseline-v2.0.sql (for creating new installations)
baseline-v2.0-upgrade-v1.0.sql (for upgrading from v1.0)
Run Code Online (Sandbox Code Playgroud)
然后该过程继续.
我们如何应用变更
脚本都保存在源代码管理中.我们有一个工具可以打包这些文件并自动升级我们的支持和安装团队使用的数据库.该工具计算出目标数据库的当前基线,并询问用户是否希望升级到包中的基线.如果他们这样做,并且当前版本存在有效的升级路径,则会应用升级脚本并更新schema_version.baseline,并从先前的基线中删除更改脚本的所有条目.如果数据库是新的,则它应用常规基线脚本.无论哪种方式,在实现基线之后,它会在事务中按顺序应用程序包中存在的所有更改脚本.如果特定的更改脚本失败,它将回滚最后一组更改和错误.我们查看日志,修复任何问题,然后重新运行包.此时,它应该只是在最后一个成功的更改脚本中获取,从而节省时间.
自动化和差异工具
我们不允许diff工具直接升级生产数据库.这太危险了.当然,我们使用diff工具来帮助创建我们的升级和更改脚本,但是一旦我们拥有它们,我们梳理它们,按摩它们,测试它们等,然后根据上面的规范创建升级或更改脚本.我们使用工具/ shell脚本来创建更改脚本文件并schema_version检查锅炉板.
注意事项
它实际上是非常直接的,它运作良好.唯一真正变得棘手的是分支机构.在大多数情况下,分支机构处理得很好.如果我们需要一个特定分支工作的更改脚本,一旦我们将分支合并回来,它将很好地折叠到主线.没问题.它变得棘手的地方是两个分支尝试做类似的事情,或者一个分支依赖另一个分支.但这主要是一个过程和计划问题.如果我们遇到这种情况,我们只需创建一个新的基线(比如说v2.1),然后相应地更新分支.
要记住的另一件事是,如果安装想要从一个基线升级到另一个基线,则必须在升级到新基线之前应用当前基线的所有未完成的更改.换句话说,我们不会让安装从它们的任何位置跳到下一个基线(当然,除非它们已经是当前基线的最新版本).
Sti*_*ack 11
我建议使用SQL Server数据工具和/或Visual Studio SQL数据库项目.它会将您现有的数据库反向工程为可以进行版本控制的代码(sql)文件,并提供许多其他细节(发布,比较等)
我们专门开发了SQL Source Control来解决您描述的问题.它扩展了SSMS,以提供SQL Server架构对象(和静态数据)与现有源代码控制系统之间的链接.
http://www.red-gate.com/products/sql-development/sql-source-control/
如果您需要更多信息,我们非常乐意提供帮助(联系support@red-gate.com)