VSTS构建 - 分布式环境中的增量数据库部署

时间:2017-06-14 06:41:18

标签: sql-server continuous-integration sql-server-data-tools azure-pipelines database-deployment

我有一个使用.net 2015 mvc 5应用程序的sql server数据库。我的数据库代码是使用SSDT项目控制源代码的。我正在使用SqlPackage.exe使用SSDT项目构建过程创建的.Decpac文件将数据库部署到登台环境。这是使用VSTS构建的PowerShell任务完成的。 这样我就可以以源代码控制的方式进行数据库架构更改。现在问题是关于数据库的主数据插入。

我使用的sql脚本文件包含数据插入脚本,该脚本作为后期部署脚本执行。此文件也受源控制。

问题在于,最初我们已经准备好插入脚本来定位sprint(以sprint n为基础),这适用于首次发布。但是在下一个sprint中,如果更新了一些主数据,那么应该如何更新主数据插入:

  1. 在脚本文件的最后添加新的更新/插入查询?但在这种情况下,后部署脚本将由CI执行,它会尝试在后续构建中反复插入数据,如果我们在此数据库的主表中进行了一些架构更改,则最终会失败。
  2. 更新数据插入脚本中的现有插入查询。在这种情况下,我们也遇到了麻烦,因为在post build事件中,将重新插入整个数据。
  3. 为每个脚本维护单独的数据插入脚本,并将脚本引用更新为SSDT的后期构建事件的新文件。这种方法有手动操作和错误,因为开发人员必须记住这个过程。此方法的另一个问题是,如果我们需要在分布式服务器场中再设置一个数据库服务器。多个数据插入脚本将抛出错误,因为SSDT具有最新的模式,并且它将创建具有相同的数据库。但是较旧的数据脚本具有先前模式的数据插入(sprint明智的数据库模式,后来的冲刺中已更改)
  4. 所以任何人都可以建议手动工作量较少的最佳方法,但它可以涵盖所有上述情况。

    由于 Rupendra

3 个答案:

答案 0 :(得分:1)

确保部署前和部署后脚本始终是幂等的。但是,您想实现哪种取决于您。这些脚本应该可以运行任意次,并且始终可以产生正确的结果。 因此,如果您的架构更改会影响部署脚本,那么更新脚本就是这些更改的依赖项,并且会在源代码管理中附带这些更改。 数据库版本控制已经是SSDT的内置功能。在项目文件本身中,有一个版本节点。 VSTS中有大量的版本控制构建任务,您也可以免费使用它进行版本控制。当SqlPackage.exe发布已经设置了数据库版本的项目时,将在msdb.dbo.sysdac_instances中更新一条记录。这比尝试管理,更新等自己的本地版本解决方案要容易得多。而且,您不会用表和其他与应用程序本身无关的对象来弄乱应用程序的数据库。 我同意不要混用sprint信息。 在我们的项目中,我用构建号标记成功构建中的源,这当然会在源中创建链接到特定构建的时间点标记。

答案 1 :(得分:0)

我建议使用MERGE语句而不是insert。这样,您就可以在sprint范围内对重复插入进行保护。

接下来是如何区分不同sprint的不同插入。我建议实现版本编号以与sprint同步数据库。所以创建一个表DbVersion(版本int)。 然后在部署后脚本中执行以下操作:

SET @version = SELECT ISNULL(MAX(version), 0) FROM DbVersion 
IF @version < 1
 --inserts/merge for sprint 1
IF @version < 2
 --inserts/merge for sprint 2
...
INSERT INTO DbVersion(@currentVersion)

答案 2 :(得分:0)

What I have done on most projects is to create MERGE scripts, one per table, that populate "master" or "static" data. There are tools such as https://github.com/readyroll/generate-sql-merge that can be used to help generate these scripts.

These get called from a post-deployment script, rather than in a post-build action. I normally create a single (you're only allowed one anyway!) post-deployment script for the project, and then include all the individual static data scripts using the :r syntax. A post-deploy script is just a .sql file with a build action of "Post-Deploy", this can be created "manually" or by using the "Add New Object" dialog in SSDT and selecting Script -> Post-Deployment Script.

These files (including the post-deploy script) can then be versioned along with the rest of your source files; if you make a change to the table definition that requires a change in the merge statement that populates the data, then these changes can be committed together.

When you build the dacpac, all the master data will be included, and since you are using merge rather than insert, you are guaranteed that at the end of the deployment the contents of the tables will match the contents of your source control, just as SSDT/sqlpackage guarantees that the structure of your tables matches the structure of their definitions in source control.

I'm not clear on how the notion of a "sprint" comes into this, unless a "sprint" means a "release"; in this case the dacpac that is built and released at the end of the sprint will contain all the changes, both structural and "master data" added during the sprint. I think it's probably wise to keep the notion of a "sprint" well away from your source control!