33

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

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

ETC...

4

8 回答 8

8

Liquibase

liquibase.org:

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

http://www.liquibase.org

于 2008-09-22T02:04:06.543 回答
6

观点

应用程序永远不应该处理模式更新。这是一场等待发生的灾难。数据比应用程序更持久,并且一旦多个应用程序尝试使用相同的数据(例如生产应用程序 + 报告应用程序)——它们很可能都将使用相同的底层公司库......然后两个程序都决定做他们自己的数据库升级......玩得开心

于 2008-09-22T02:08:27.673 回答
4

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

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

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

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

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

于 2008-08-27T09:05:17.927 回答
4

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

于 2008-08-27T09:18:36.833 回答
3

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

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

客户端设计 - 这是内联 sql 的 VB 方法(即使使用准备好的语句)给您带来麻烦的地方。您可以花费 AGES 来查找这些语句。如果您使用 Hibernate 之类的东西并将尽可能多的 SQL 放入命名查询中,则大多数 sql 都有一个位置(没有比尝试测试某些 IF 语句中的 sql 更糟糕的了,而您只是没有点击“触发器” IF 语句的测试标准)。在使用休眠(或其他形式)之前,当我直接在 JDBC 或 ODBC 中执行 SQL 时,我会将所有 sql 语句作为对象的公共字段(具有命名约定)或属性文件(也具有命名值的约定说 PREP_STMT_xxxx。即使对于一个好的 rdbms 的 100 条语句,也只需几秒钟。而且只有一次。它为我的屁股节省了很多。在一个项目中,DBA 不会沟通(不同的团队,在不同的国家),并且架构似乎每晚都在无缘无故地发生变化。每天早上,我们都会在启动时获得一份应用程序崩溃的确切位置列表。即使对于一个好的 rdbms 的 100 条语句,也只需几秒钟。而且只有一次。它为我的屁股节省了很多。在一个项目中,DBA 不会沟通(不同的团队,在不同的国家),并且架构似乎每晚都在无缘无故地发生变化。每天早上,我们都会在启动时获得一份应用程序崩溃的确切位置列表。

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

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

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

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

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

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

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

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

它已经到了想要添加新功能或优化代码的地步。一些现有的代码使用了存储过程,所以我们有共同点可以管理代码。但其他领域是 html 中嵌入的 sql 标记。这对于快速进入市场非常有用,但是随着新功能的每次交互,测试和维护的成本至少会翻倍。因此,当我们考虑提取 php 类型代码、放入数据层(这是 2001-2002 年,之前的任何 ORM 等)并添加许多新功能(客户反馈)时,我们关注了如何设计升级的问题进入系统。这很重要,因为升级要花很多钱才能正确完成。现在,大多数模式和人们在一定程度上讨论的所有其他内容都涉及正在运行的 OO 代码,

考虑到这一点,我开始玩一些偏左的东西。它也有一些假设。a) 数据读多于写。b)确实会发生更新,但不会发生在银行级别,即。一到二秒说。

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

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

于 2008-08-27T09:37:14.123 回答
2

这些都是重量级的话题,但这里是我的更新建议。

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

于 2008-08-30T03:46:48.733 回答
1

我听说过关于iBATIS 3 Schema Migrations System的好消息:

用户指南: http: //svn.apache.org/repos/asf/ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-Migrations.pdf

于 2009-11-11T13:15:02.957 回答
0

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

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

但是 liquibase 比这更有组织!

于 2010-05-22T02:16:39.107 回答