如何管理生产数据库的模式升级?

问题描述 投票:33回答:8

这似乎是一个被忽视的领域,可以真正使用一些洞察力。您的最佳做法是:

  • 进行升级程序
  • 在出现错误时退出
  • 同步代码和数据库更改
  • 在部署之前进行测试
  • 修改表的机制

等等...

oracle database-administration
8个回答
3
投票

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

我做过的一些事情(当我有更多时间或需要休息时会增加更多)

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

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

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

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

管理对架构的更改 - >您是否更新表或向新表添加1-1关系?由于这个原因,我看到很多商店总是通过视图访问数据。这允许表名更改,列等。我已经实现了实际处理COM中的接口之类的视图的想法。即。为新功能/版本添加新的VIEW。通常情况下,您可以获得许多采用表格格式的报告(尤其是最终用户自定义报告)。这些视图允许您部署新的表格格式,但支持现有的客户端应用程序(请记住所有那些讨厌的特殊报告)。

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

------------好的 - 这是一个随机的讨论时间--------------

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

进行升级需花费很多钱。很多。即。在网站上免费提供数周的免费咨询时间。

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

考虑到这一点,我开始玩一些有点遗留的东西。它也有一些假设。 a)数据读取多于写入。 b)更新确实发生,但不是在银行层面,即。一两秒钟说。

我们的想法是将COM /接口视图应用于客户端如何通过一组CONCRETE表(随架构更改而变化)访问数据。您可以为每种类型操作创建单独的视图 - 更新,删除,插入和读取。这个很重要。视图将直接映射到表,或允许您触发执行真实更新或插入等的虚拟表。我真正想要的是某种可以被水晶报表使用的可捕获级别间接。 - 对于插入,更新和删除,您还可以使用存储过程。并且每个版本的产品都有一个版本。这样你的版本1.0就有了它的模式版本,如果表格发生变化,你仍然可以使用版本1.0 VIEWS但是有新的后端逻辑可以根据需要映射到新表格,但你也有2.0版本的视图可以支持新的领域等。这实际上只是为了支持临时报告,如果您的业务人员而不是编码员可能是您拥有该产品的原因。 (你的产品可能是垃圾,但如果你拥有世界上最好的报告,你仍然可以获胜,反过来也是如此 - 你的产品可能是最好的功能,但如果报告的情况更糟,你很容易就会松动)。

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


8
投票

Liquibase

里去I base.org:

  1. 它理解hibernate的定义。
  2. 它比hibernate生成更好的架构更新sql
  3. 它记录已对数据库进行的升级
  4. 它处理两步更改(即删除列“foo”,然后将另一列重命名为“foo”)
  5. 它处理条件升级的概念
  6. 开发人员实际上是在监听社区(如果你不在“in”人群中或者是新手,那么hibernate也是如此 - 你基本上被忽略了。)

http://www.liquibase.org


6
投票

意见

应用程序永远不应该处理架构更新。这是一场等待发生的灾难。数据比应用程序更长,一旦多个应用程序尝试使用相同的数据(例如生产应用程序+报告应用程序),他们就有可能使用相同的基础公司库......然后两个程序都决定做自己的数据库升级......玩得很开心。


4
投票

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


4
投票

一般来说,我的规则是:“应用程序应该管理它自己的架构。”

这意味着架构升级脚本是应用程序的任何升级包的一部分,并在应用程序启动时自动运行。如果出现错误,应用程序将无法启动,并且未提交升级脚本事务。这样做的缺点是应用程序必须具有对模式的完全修改访问权限(这会使DBA烦恼)。

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

关于测试,由于升级是应用程序的一部分,因此测试它们将成为应用程序测试周期的一部分。

事后的想法:在这里接受其他帖子中的一些批评,注意规则说“它是自己的”。它仅适用于应用程序拥有架构的情况,通常是作为产品销售的软件的情况。如果您的软件与其他软件共享数据库,请使用其他方法。


2
投票

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

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



0
投票

正如Pat所说,使用liquibase。特别是当您有多个开发人员拥有自己的开发人员数据库时,他们会进行更改,这些更改将成为生产数

如果只有一个dev,就像我现在正在使用的一个项目(ha),我只是将架构更改作为SQL文本文件提交到CVS仓库中,当代码更改进入时,我会在生产服务器上批量检出。

但liquibase组织得比这更好!

© www.soinside.com 2019 - 2024. All rights reserved.