[英]How should you build your database from source control?
关于数据库对象是否应该受版本控制的SO社区wiki已经有一些讨论。 但是, 我没有看到很多关于为数据库对象创建构建自动化过程的最佳实践的讨论。
这对我的团队来说是一个有争议的讨论点 - 特别是在评估数据库部署自动化方法的优势和风险时,开发人员和DBA通常有不同的目标,方法和关注点。
我想听听SO社区关于哪些实践在现实世界中有效的一些想法。
我意识到这有点主观,哪些实践真的是最好的,但我认为一个关于哪些工作可能对许多人有帮助的良好对话。
以下是我在此主题中关注领域的一些预告片问题。 这些并不是一个明确的清单 - 而是人们帮助理解我正在寻找的东西的起点。
我尽可能将SQL视为源代码
如果我可以在标准的兼容SQL中编写它,那么它通常会在我的源代码控制中的文件中。 该文件将尽可能多地定义,例如SP,表CREATE语句。
我还包括用于源代码控制测试的虚拟数据:
然后我抽象出所有的SQL查询,以便我可以为MySQL,Oracle,MSSQL或其他任何东西构建整个项目。
构建和测试自动化使用这些构建脚本,因为它们与应用程序源一样重要,并测试从完整性到触发器,过程和日志记录的所有内容。
Liquibase的 +1: LiquiBase是一个开源(LGPL),独立于数据库的库,用于跟踪,管理和应用数据库更改。 它建立在一个简单的前提上:所有数据库更改(结构和数据)都以基于XML的描述方式存储,并检入源代码控制。 好的一点是,DML更改是在语义上存储的,而不仅仅是diff,因此您可以跟踪更改的目的。
它可以与GIT版本控制相结合,以实现更好的交互。 我将配置我们的dev-prod环境来试用它。
您还可以使用Maven,Ant构建系统从脚本构建生产代码。
减去的是LiquiBase没有集成到广泛的SQL IDE中,你应该自己做基本的操作。
除此之外 ,您还可以使用DBUnit进行数据库测试 - 此工具允许数据生成脚本用于测试您的生产环境并进行清理。
恕我直言:
我们在计费生产数据库中遇到了所有提到的代码更改,合并和重写问题。 这个主题非常适合发现所有这些内容。
我们通过TeamCity使用持续集成。 在每次签入源代码控制时,从头开始重新构建数据库和所有测试数据,然后是代码,然后针对代码运行单元测试。 如果您正在使用像CodeSmith这样的代码生成工具,它也可以放入您的构建过程中,以便在每次构建时生成新的数据访问层,确保所有层“匹配”并且不会因为SP参数不匹配或缺少列。
每个构建都有自己的SQL脚本集合,这些脚本存储在源代码管理的$ project \\ SQL \\目录中,分配了一个数字前缀并按顺序执行。 这样,我们就会在每次构建时练习我们的部署过程。
根据查找表,我们的大多数查找值也存储在脚本中并运行以确保配置数据符合我们的预期,例如“reason_codes”或“country_codes”。 这样我们就可以在开发中进行查找数据更改,测试它然后通过QA和生产“提升”它,而不是使用工具来修改生产中的查找值,这对正常运行时间来说是危险的。
我们还创建了一组“回滚”脚本来撤消我们的数据库更改,以防生产构建变得棘手。 您可以通过运行它们来测试回滚脚本,然后在部署脚本运行后重新运行低于您的版本的单元测试。
我基本同意van给出的每一个答案。 更深入的了解,我的数据库管理基准是K. Scott Allen系列 (必读,恕我直言。而且看来Jeff也是如此)。
Create.sql
。 这可以包括静态数据插入(列表......)。 Create.sql
: Create.cmd
。 它的目标主要是检查先决条件(工具,环境变量......)并将参数发送到SQL脚本。 它还可以批量加载 CSV文件中的静态数据,以解决性能问题。 Create.cmd
文件。 恕我直言, 动态数据加载应该需要另一个步骤,具体取决于您的环境。 开发人员希望根据测试,垃圾或无数据加载他们的数据库,而在另一端,生产经理将希望加载生产数据。 我也会考虑将测试数据存储在源代码控制中(例如,为了简化单元测试)。
一旦数据库的第一个版本投入生产,您不仅需要构建脚本(主要用于开发人员),还需要升级脚本(基于相同的原则):
Upgrade.sql
文件(可以调用其他文件),允许将版本N-1升级到版本N(N是正在发布的版本)。 我将此脚本存储在名为N-1
的文件夹下。 Upgrade.cmd
。 它可以通过简单的SELECT语句检索数据库的当前版本(CV),启动存储在CV
文件夹下的Upgrade.sql
脚本,然后循环直到找不到文件夹。 这样,您可以自动从N-3升级到N. 这个问题是:
至于您希望在源代码管理下拥有哪种数据库对象? 好吧,我会尽可能地说,但不是更多;-)如果你想用密码创建用户,给他们一个默认密码(登录/登录,实用于单元测试目的),并使密码更改为手动操作。 这种情况在Oracle中发生很多,其中模式也是用户...
通过询问“预告片问题”,您似乎对某个讨论更感兴趣,而不是某人对最终答案的看法。 活跃的(> 2500个成员)邮件列表agileDatabases解决了许多这些问题,根据我的经验,这是一个用于此类讨论的复杂而民用的论坛。
而不是进入白塔争论,这是一个解决方案,对我来说在现实世界问题上非常有效。
从头开始构建数据库可以概括为管理sql脚本。
DBdeploy是一个检查数据库当前状态的工具 - 例如,之前运行过哪些脚本,可以运行哪些脚本,以及需要运行哪些脚本。
然后它会将所有需要的脚本整理在一起并运行它们。 然后它记录已运行的脚本。
它不是最漂亮的工具或最复杂的工具 - 但通过精心管理,它可以很好地工作。 它是开源的,易于扩展。 一旦很好地处理了脚本的运行,就可以轻松地添加一些额外的组件,例如shell脚本,它可以检查最新的脚本并针对特定实例运行dbdeploy。
在这里看一个很好的介绍:
我们在Git版本控制中使用带有MSSQL数据库的Silverlight项目。 最简单的方法是确保你有一个精简的数据库(内容明智),并从fe Visual Studio 完成转储。 然后,您可以从构建脚本执行'sqlcmd',以在每台开发机器上重新创建数据库。
对于部署,这是不可能的,因为数据库太大:这是将它们放在数据库中的主要原因。
我坚信DB应该是源代码控制的一部分,并且在很大程度上是构建过程的一部分。 如果它在源代码控制中,那么在SQL中编写存储过程时,我就像在C#中编写类时一样,具有相同的编码安全保护。 我通过在源代码树下包含一个DB脚本目录来完成此操作。 此脚本目录不一定有一个文件用于数据库中的一个对象。 这将是一个痛苦的屁股! 我在我的数据库中开发只是我想在我的代码项目中。 然后当我准备好检查时,我在我的数据库的最后一个版本和我正在处理的当前版本之间做了一个差异。 我为此使用SQL Compare,它会生成所有更改的脚本。 然后将此脚本保存到我的db_update目录,其中包含特定的命名约定1234_TasksCompletedInThisIteration,其中该数字是已存在的脚本集中的下一个数字,名称描述了此检查中正在执行的操作。我这样做是因为as我的构建过程的一部分,我从一个新的数据库开始,然后使用此目录中的脚本以编程方式构建。 我编写了一个自定义的NAnt任务,它遍历在裸db上执行其内容的每个脚本。 显然,如果我需要一些数据进入数据库,那么我也有数据插入脚本。 这也有很多好处。 一,我所有的东西都是版本的。 二,每个构建都是一个新构建,这意味着不会有任何偷偷摸摸的东西进入我的开发过程(例如导致系统奇怪的脏数据)。 三,当一个新人被添加到开发团队时,他们只需要获得最新信息,他们的本地开发人员即可为他们构建。 四,我可以在我的数据库上运行测试用例(我没有把它称为“单元测试”!),因为每次构建都会重置数据库的状态(这意味着我可以测试我的存储库而不必担心将测试数据添加到D b)。
这不适合所有人。
这不适用于每个项目。 我经常在绿色的田野项目上工作,这让我很方便!
您可能会发现Liquibase处理了很多您正在寻找的东西。
每个开发人员都应该拥有自己的本地数据库,并使用源代码控制来发布给团队。 我的解决方案在这里: http : //dbsourcetools.codeplex.com/玩得开心, - Nathan
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.