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

Mar*_*son 33 oracle database-administration

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

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

等等...

Pat*_*Pat 8

liquibase.org:

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

http://www.liquibase.org


Pat*_*Pat 6

意见

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


Joh*_*ter 5

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


nso*_*so1 4

这是一个很好的问题。(这很可能会引发一场规范化与非规范化数据库的辩论……我不打算开始……好吧,现在提供一些意见。)

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

客户端设计 - 这是内联 sql 的 VB 方法(即使使用准备好的语句)给您带来麻烦的地方。您可能会花费很长时间才能找到这些陈述。如果你使用 Hibernate 之类的东西,并将尽可能多的 SQL 放入命名查询中,那么你就有一个地方可以存放大部分 sql(没有什么比尝试测试某些 IF 语句中的 sql 而你只是没有点击“触发器”更糟糕的了) IF 语句测试中的标准)。在使用 hibernate(或其他 orms)之前,当我直接在 JDBC 或 ODBC 中执行 SQL 时,我会将所有 sql 语句作为对象的公共字段(具有命名约定)或属性文件中(也具有命名约定)。值的约定为 PREP_STMT_xxxx。并在 a) 测试用例 b) 应用程序启动时使用反射或迭代启动时的值(某些 RDBMS 允许您在执行前使用准备好的语句进行预编译,因此在登录后启动时我会在启动时预编译 prep-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 版视图新领域等。这实际上只是为了支持临时报告,如果您是业务人员而不是编码员,那么这可能就是您拥有该产品的全部意义。(你的产品可能很糟糕,但如果你拥有世界上最好的报告,你仍然可以获胜,反之亦然 - 你的产品可能是最好的功能,但如果它的报告最差,你很容易就会失败)。

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

  • 这是如何成为公认的答案的?它如何回答原始问题中的要点? (8认同)