2008-08-27 59 views
32

这似乎是一个可以真正使用一些见解的被忽略的区域。什么是您的最佳做法:如何管理对生产数据库的模式升级?

  • 使升级过程
  • 在错误
  • 同步代码和数据库的情况下打了退堂鼓变化
  • 部署之前测试修改表
  • 力学

etc ...

+0

我很惊讶没有更多的答案在这里 - 也许需要特定的oracle或sqlserver标签? – 2009-11-11 13:10:24

+0

不错的主意,谢谢! – 2009-11-11 23:22:04

回答

3

这是一个很好的问题。 (这很有可能会导致规范化与非规范化的数据库争论......我不会开始......现在可以进行一些输入。)

有些脱离我头脑的东西我(当我有更多的时间或需要休息时将增加更多)

客户端设计 - 这是内联sql的VB方法(甚至准备好语句)让你陷入困境。您可以花AGES找到这些陈述。如果你使用像Hibernate这样的东西,并将尽可能多的SQL放入命名查询中,那么对于大多数sql来说,只有一个位置(没有比试图测试某些IF语句内部的sql更糟糕的事情,而且你不会触及“触发器”您对该IF语句进行测试的标准)。当我直接在JDBC或ODBC中执行SQL时,在使用hibernate(或其他orms')之前,我会将所有的sql语句作为对象的公共字段(使用命名约定)或属性文件中(也使用命名约定的值为PREP_STMT_xxxx。使用反射或在启动时迭代a)测试用例b)启动应用程序(某些rdbms允许您在执行前用预准备语句进行预编译,所以在启动后登录I将在启动时预编译准备工作,以使应用程序自我测试,即使是在一个好的rdbms上只有几秒钟,也只有一次的100个语句,并且它已经节省了很多。在一个项目中,DBA不会沟通(一个不同的团队,在不同的国家),模式似乎没有理由改变。每天早上,我们都会在启动时收到一份清单,说明它打破了应用程序的位置。

如果你需要adhoc功能,把它放在一个很好命名的类(即一个命名约定有助于自动配对测试),作为某种工厂供你查询(即建立查询)。无论如何,你将不得不编写相应的代码,只需放在一个可以测试的地方。你甚至可以在同一个对象上或者在一个单独的类中编写一些基本的测试方法。

如果可以,还尝试使用存储过程。他们有点难以像上面那样测试。有些db也不会在运行时在编译时根据模式预先验证存储过程中的sql。它通常涉及说取一个模式结构的副本(没有数据),然后创建所有存储的特效对这个副本(如果数据库团队进行更改DID不正确验证)。因此可以检查结构。但作为一个变化点管理存储过程是伟大的。在变化都得到它。特别是当数据库更改是业务流程更改的结果时。并且所有的语言(java,vb等都会得到这个改变)

我通常还会设置一个我使用的名为system_setting的表格等。在这个表格中我们保留一个VERSION标识符。这样,客户端库可以连接并验证它们是否适用于此版本的模式。根据对模式的更改,如果客户端可能会损坏模式(例如,数据库中没有大量的参照规则,但在客户端上),则不希望允许客户端进行连接。这取决于你是否也有多个客户端版本(这在非网络应用中发生,即它们运行错误的二进制文件)。你也可以有批处理工具等。我也做过的另一种方法是在某种属性文件中或在system_info表中再定义一组操作版本的操作版本。这个表在登录时加载,然后由每个“管理器”(我通常有某种客户端API做大多数数据库的东西)来验证该操作,如果它是正确的版本。因此大多数操作都可以成功,但是你也可能会失败(抛出一些例外)过时的方法,并告诉你为什么。

管理对模式的更改 - >你更新表或添加1-1关系到新表吗?出于这个原因,我看到很多商店总是通过视图访问数据。这允许表名改变,列等。我玩过的观点实际上像COM中的接口一样处理。即。您为新功能/版本添加了新的VIEW。通常情况下,您在这里得到的是您可以拥有许多假设表格格式的报告(特别是最终用户自定义报告)。视图允许您部署新的表格格式,但支持现有的客户端应用程序(请记住所有讨厌的特别报告)。

另外,需要编写更新和回滚脚本。并再次测试,测试,测试...

------------ OKAY - 这是一个位有限的讨论时间--------------

实际上有一个大型商业项目(即软件商店),我们遇到了同样的问题。该架构是一个2层,他们使用的产品有点像PHP,但在pre-php。一样。不同的名字。无论如何,我进来版本2 ....

这是花了很多钱做升级。很多。即。现场免费提供数周的咨询时间。

而它正在想要添加新功能或优化代码。一些现有的代码使用了存储过程,所以我们有共同点来管理代码。但其他地区是这个嵌入式的标记在HTML中。这对于迅速进入市场很有好处,但每次新功能的交互都会使成本至少增加一倍以便测试和维护。因此,当我们考虑将php类型代码拉出来时,将数据层(2001-2002,任何ORM等)放入数据层并添加大量新功能(客户反馈)来查看如何设计UPGRADES进入系统。这是一件大事,因为升级需要花费大量金钱才能正确执行。现在,大多数模式和所有其他人都在讨论一定程度的能量处理OO代码,但是你的数据必须与这个逻辑相结合,b)意义和结构数据会随着时间而改变,而且通常由于数据的工作方式,最终会在客户组织中产生大量需要该数据的子流程/应用程序 - >即席报告或任何复杂的自定义报告以及批处理作业已经完成了自定义数据馈送等。

考虑到这一点,我开始玩点左边的东西。它也有一些假设。 a)数据严重超出了写入的范围。 b)更新确实发生,但不在银行级别,即。一秒钟或二秒钟说。

这个想法是将一个COM /接口视图应用于客户端通过一组CONCRETE表访问数据的方式(随架构变化而变化)。您可以为每个类型操作创建一个单独的视图 - 更新,删除,插入和读取。这个很重要。这些视图可以直接映射到一个表格,也可以让你触发一个真正的更新或插入的虚拟表格等。我真正想要的是某种可以被水晶报告等使用的可捕获级别间接方式。 - 对于插入,更新和删除你也可以使用存储的特效。你有一个版本的每个版本的产品。这样你的1.0版本就有了它的模式版本,如果表格改变了,你仍然可以使用1.0版本的VIEWS,但是新的后端逻辑根据需要映射到新表格,但是你也有2.0版本的视图支持新的领域等。这实际上只是为了支持临时报告,如果您的业务人员而不是编码人员可能是您拥有产品的原因。 (您的产品可能是废话,但如果您拥有世界上最好的报告,您仍然可以获胜,但事实恰恰相反 - 您的产品可能是最好的功能,但如果报告更差,您可以轻松放弃)。

好的,希望其中的一些想法有所帮助。

+6

这是如何成为公认的答案?它如何回答原始问题中的观点? – 2009-11-11 13:04:31

4

一般而言,我的规则是:“应用程序应该管理它自己的模式。”

这意味着模式升级脚本是应用程序的任何升级包的一部分,并在应用程序启动时自动运行。如果发生错误,应用程序无法启动并且升级脚本事务未提交。这样做的缺点是应用程序必须对模式进行完整的修改访问(这让数据库管理员很烦恼)。

使用Hibernates SchemaUpdate功能来管理表结构,我取得了巨大的成功。让升级脚本只处理实际的数据初始化和偶尔删除列(SchemaUpdate不会这样做)。

关于测试,由于升级是应用程序的一部分,因此测试它们成为应用程序测试周期的一部分。事后思考:考虑到其他职位的一些批评,请注意规则说“它是自己的”。它只适用于应用程序拥有架构,通常与作为产品销售的软件一样。如果您的软件与其他软件共享数据库,请使用其他方法。

4

我是Red Gate产品的粉丝,帮助创建SQL包来更新数据库模式。可以将数据库脚本添加到源代码管理中,以帮助进行版本控制和回滚。

2

这些都是重要的主题,但这里是我的更新建议。

您没有指定您的平台,但对于我使用的NANT构建环境Tarantino。对于准备提交的每个数据库更新,您都可以创建更改脚本(使用RedGate或其他工具)。当你生产到生产时,Tarantino会检查脚本是否已经在数据库上运行(它向你的数据库添加一个表来跟踪)。如果没有,脚本运行。它将所有手动工作(读取:人为错误)从管理数据库版本中取出。

8

liquibase.org:

  1. 它理解冬眠的定义。
  2. 它会产生更好的架构更新SQL比冬眠
  3. 其升级已对数据库
  4. 它处理两个步骤的改变它的日志(即删除列“富”,然后重命名不同的列到“富“)
  5. 它处理条件升级的概念
  6. 开发人员实际上倾听社区(如果您不在”人群中“或新手 - 您基本上被忽略,则使用hibernate。)

http://www.liquibase.org

6

意见

应用程序应该从未处理架构更新。这是一场等待发生的灾难。数据超过了应用程序,并且一旦多个应用程序尝试使用相同的数据(例如生产应用程序+报告应用程序) - 他们可能会使用相同的基础公司库......然后,这两个程序决定做自己的数据库升级...与混乱。

0

正如帕特说,使用liquibase。特别是当您有几个开发人员使用他们自己的开发数据库 进行将成为生产数据库一部分的更改时。

如果只有一个开发工具,就像我现在在一个项目上一样(ha),我只是将模式更改作为SQL文本文件提交到一个CVS回购库中,我在生产服务器上批量检出代码更改进入。

但是liquibase组织比这更好!