这似乎是一个被忽视的领域,确实需要一些洞察力。您的最佳实践是什么:

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

ETC...

有帮助吗?

解决方案

这是一个很好的问题。(这很可能会引发一场规范化与非规范化数据库的争论......我不打算开始......现在可以输入一些信息了。)

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

客户端设计 - 这是内联 sql 的 VB 方法(即使使用准备好的语句)给您带来麻烦的地方。您可能会花费很长时间才能找到这些陈述。如果你使用 Hibernate 之类的东西,并将尽可能多的 SQL 放入命名查询中,那么你就有一个地方可以存放大部分 sql(没有什么比尝试测试某些 IF 语句中的 sql 而你只是没有点击“触发器”更糟糕的了) IF 语句测试中的标准)。在使用 hibernate(或其他 orms)之前,当我直接在 JDBC 或 ODBC 中执行 SQL 时,我会将所有 sql 语句作为对象的公共字段(具有命名约定)或属性文件中(也具有命名约定)。值的约定为 PREP_STMT_xxxx。并在 a) 测试用例 b) 应用程序启动时使用反射或迭代启动时的值(某些 RDBMS 允许您在执行前使用准备好的语句进行预编译,因此在登录后启动时我会预编译准备好的语句) stmts 在启动时使应用程序进行自我测试。即使对于好的 RDBMS 上的 100 条语句,也只需几秒钟。并且只有一次。它节省了我很多屁股。在一个项目中,DBA 不会进行沟通(不同的团队,在不同的国家),而且架构似乎每晚都会无缘无故地改变。每天早上我们都会收到一份在启动时破坏应用程序的确切位置的列表。

如果您需要临时功能,请将其放入一个命名良好的类中(即同样,命名约定有助于自动测试),它充当您查询的某种工厂(即它构建查询)。无论如何,您都必须编写等效的代码,只需将其放在可以测试的地方即可。您甚至可以在同一个对象或单独的类中编写一些基本的测试方法。

如果可以的话,也尝试使用存储过程。如上所述,它们的测试有点困难。一些数据库也不会在编译时仅在运行时根据模式预先验证存储过程中的 sql。它通常涉及获取模式结构的副本(无数据),然后根据该副本创建所有存储过程(以防数据库团队进行更改未正确验证)。从而可以检查结构。但作为变更管理的一个点,存储过程非常棒。改变一切都明白了。特别是当数据库更改是业务流程更改的结果时。所有语言(java、vb 等都会发生变化)

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

管理架构更改 -> 您是否更新表或向新表添加 1-1 关系?由于这个原因,我见过很多商店总是通过视图访问数据。这允许更改表名、列等。我曾尝试过将视图实际视为 COM 中的接口。IE。您为新功能/版本添加新视图。通常,您会遇到很多采用表格格式的报告(尤其是最终用户自定义报告)。这些视图允许您部署新的表格式,但支持现有的客户端应用程序(记住所有那些讨厌的临时报告)。

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

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

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

升级需要花费很多钱。很多。IE。赠送数周的免费现场咨询时间。

现在已经到了想要添加新功能或优化代码的地步。一些现有代码使用存储过程,因此我们有可以管理代码的共同点。但其他领域是 html 中嵌入的 sql 标记。这对于快速进入市场来说非常有用,但随着新功能的每次交互,测试和维护的成本至少增加了一倍。因此,当我们考虑取出 php 类型代码、放入数据层(这是 2001-2002 年,在任何 ORM 之前等)并添加许多新功能(客户反馈)时,我们考虑了如何设计升级的问题进入系统。这是一件大事,因为正确的升级需要花费很多钱。现在,人们在一定程度上讨论的大多数模式和所有其他内容都涉及正在运行的 OO 代码,但是您的数据必须 a) 集成到此逻辑,b) 的含义和结构,这一事实又如何呢?数据可能会随着时间的推移而变化,并且通常由于数据的工作方式,您最终会在客户组织中产生大量需要该数据的子流程/应用程序 -> 特别报告或任何复杂的自定义报告以及批处理作业已经为自定义数据源等完成了这些操作。

考虑到这一点,我开始尝试一些有点偏左的东西。它还有一些假设。a) 数据的读取次数多于写入次数。b) 更新确实发生,但不是在银行级别,即。每秒说一两个。

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

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

其他提示

液体碱

liquibase.org:

  1. 它理解休眠定义。
  2. 它生成比 hibernate 更好的模式更新 sql
  3. 它记录对数据库进行的升级
  4. 它处理两步更改(即删除列“foo”,然后将不同的列重命名为“foo”)
  5. 它处理条件升级的概念
  6. 开发人员实际上会倾听社区的意见(如果您不是“圈内”人群或新手,那么您基本上会被忽略。)

http://www.liquibase.org

观点

该应用程序应该 绝不 处理架构更新。这是一场即将发生的灾难。数据比应用程序更持久,一旦多个应用程序尝试使用相同的数据(例如生产应用程序+报告应用程序)——它们很可能都会使用相同的底层公司库......然后两个程序都决定进行自己的数据库升级......从...中得到快乐 混乱。

我是以下的忠实粉丝 红门 帮助创建 SQL 包以更新数据库架构的产品。可以将数据库脚本添加到源代码管理中以帮助进行版本控制和回滚。

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

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

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

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

事后思考:考虑到这里其他帖子中的一些批评,请注意该规则说“它是自己的”。它仅真正适用于应用程序 拥有 该架构与作为产品销售的软件的一般情况相同。如果您的软件与其他软件共享数据库,请使用其他方法。

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

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

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

如果只有一个开发人员,就像我现在正在进行的一个项目一样(ha),我只需将架构更改作为 SQL 文本文件提交到 CVS 存储库中,当代码更改进入时,我会在生产服务器上批量检查该存储库。

但 liquibase 的组织性比这更好!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top