27

好的,这就是我们面临的问题。

目前:

  1. 我们有大量可以直接访问数据库的旧版应用程序
  2. 数据库中的数据结构未规范化
  3. 几乎所有应用程序都使用当前的流程/结构

我们正在尝试实现的内容:

  1. 将所有功能移至 RESTful 服务,因此应用程序无法直接访问数据库
  2. 实现规范化的数据结构

我们遇到的问题是如何不仅使用应用程序而且还使用数据库来实现这种迁移。

我们目前的解决方案是:

  1. 识别所有 CRUD 功能并在新的 Web 服务中实现它
  2. 创建新应用程序以替换旧版应用程序
  3. 将新应用程序指向新的 Web 服务(仍然指向旧的数据结构)
  4. 将数据库中的数据迁移到新结构
  5. 将新应用程序指向新的 Web 服务(指向新的数据结构)

但是当我们讨论这个过程时,我们正在考虑必须两次重写新 Web 服务。一次用于旧数据结构,一次用于新数据结构,因为目前我们无法表示旧数据结构以适应新 Web 服务的新数据结构。

我想知道是否有人遇到过这样的挑战,以及您是如何克服这些类型的问题/实施等的。

4

3 回答 3

20

编辑:使用双向触发器进行同步的更多解释;语法、语言和清晰度的更新。

前言

在我工作了 7 年的大型 Web 应用程序的数据模型升级中,我遇到了类似的问题,所以我感受到了你的痛苦。根据这次经验,我会提出一些不同的建议——但希望它更容易实现。但首先,观察:

对组织的价值在于数据——数据将比您当前的所有应用程序寿命更长。企业将不断发明新的方法来从其捕获的数据中获取价值,这将产生新的报告、应用程序和开展业务的方式。

所以让新的数据结构正确应该是你最重要的目标。不要将结构正确与其他短期发展目标进行交易,尤其是:

  • 运营目标,例如推出新服务
  • 报告性能(使用物化视图、触发器或批处理作业)

这种结构会随着时间而改变,因此您的架构必须允许对其进行频繁的添加和不频繁的规范化。这意味着您的数据结构和任何共享的 API(包括 RESTful 服务)必须进行正确的版本控制。

为什么选择 RESTful Web 服务?

您提到您将“将所有功能移动到 RESTful 服务,因此没有应用程序可以直接访问数据库”。关于遗留应用,我需要问一个非常重要的问题:为什么这很重要,它带来了什么价值?

我问是因为:

  • 你丢失了 ACID 事务(每个调用都是一个事务,除非你实现了一些极其复杂的 WS-* 标准)
  • 性能下降:直接数据库连接将更快(无需 Web 服务器工作和翻译)并且延迟更少(通常为 1 毫秒而不是 50-100 毫秒),这将明显降低为直接数据库连接编写的应用程序的响应能力
  • 数据库结构不是从 RESTful 服务中抽象出来的,因为您承认,通过数据库规范化,您必须重写 Web 服务并重写调用它们的应用程序。

其他横切关注点保持不变:

  • 可管理性:可以在此处使用许多通用工具监视和管理直接数据库连接
  • 安全性:直接连接比开发人员编写的 Web 服务更安全,
  • 授权:数据库权限模型非常先进,可以根据需要进行细粒度
  • 可扩展性:Web 服务是(仅?)直接连接的数据库应用程序,因此只能与数据库一样扩展

您可以通过维护旧版 RESTful API 来迁移数据库并保持旧版应用程序运行。但是,如果我们可以保留遗留应用程序而不引入“遗留”RESTful 服务会怎样。

数据库版本控制

据推测,大多数“遗留”应用程序都使用 SQL 直接访问数据表;您可能还有许多数据库视图。

数据迁移的一种方法是新数据库(在新模式中具有新的规范化结构)将旧结构呈现为遗留应用程序的视图,通常来自不同的模式。

这实际上很容易实现,但只解决了报告和只读功能。遗留应用程序 DML 呢?DML可以使用解决

  • 用于简单转换的可更新视图
  • 引入无法更新视图的存储过程(例如“CALL insert_emp(?, ?, ?)”而不是“INSERT INTO EMP (col1, col2, col3) VALUES (?, ? ?)”。
  • 有一个“旧”表,它通过触发器和数据库链接与新数据库同步。

使用触发器将旧格式表与新格式表双向同步是一种蛮力解决方案,而且相对难看。

您最终会在两个不同的模式(或数据库)中获得相同的数据,并且如果同步代码有错误,数据可能会不同步 - 然后您就会遇到“双主”问题的经典问题。因此,将此作为最后的手段,例如在以下情况下:

  • 基本结构已经改变(例如改变关系的基数),或者
  • 转换为旧格式是一个复杂的函数(例如,如果旧列是新格式列值的平方并设置为“4”,可更新视图无法确定正确值是 +2 还是 -2) .

当您的数据需要进行此类更改时,某处的代码和逻辑将发生一些重大变化。您可以在兼容层中实现(优势:不更改遗留代码)或更改遗留应用程序(优势:数据层干净)。这是工程团队的技术决定。

使用上面概述的方法创建遗留结构的兼容性数据库可以最大限度地减少对遗留应用程序的更改(在某些情况下,遗留应用程序继续运行而根本没有任何代码更改)。这大大降低了开发和测试成本(对业务没有净功能收益),并大大降低了推出风险。

它还允许您专注于对组织的真正价值:

  • 新的数据库结构
  • 新的 RESTful Web 服务
  • 新应用程序(可能使用 RESTful Web 服务构建)

Web 服务的积极方面

请不要将以上内容解读为对 Web 服务,尤其是 RESTful Web 服务的诽谤。当用于正确的原因时,例如启用 Web 应用程序或不同系统之间的集成,这是一个很好的架构解决方案。但是,它可能不是在数据迁移期间管理旧应用程序的最佳解决方案。

于 2012-11-28T03:27:01.393 回答
2

看起来您应该做的是定义一个新的数据模型(“规范化”)并构建从规范化模型到旧模型的映射。然后,您可以在闲暇时将传统的直接呼叫替换为标准化呼叫。这不会破坏任何代码。

同时,您需要定义相当于(中央化)遗留数据库 api 的内容,并将其映射到您的规范化模型。现在,在您闲暇时,将原始的遗留数据库调用替换为对遗留数据库 API 的调用。这不会破坏任何代码。

一旦原始调用被完全替换,您就可以将数据模型切换到真正的规范化模型。这应该不会破坏任何代码,因为现在一切都与传统的 db API 或规范化的 db API 背道而驰。

最后,您可以用使用规范化数据 API 的修改后的代码替换旧的 db API 调用和相关代码。这需要仔细重新编码。

为了加快这一切,您需要一个自动代码转换工具来实现代码替换。

该文档似乎有一个很好的概述: http ://se-pubs.dbs.uni-leipzig.de/files/Cleve2006CotransformationsinDatabaseApplicationsEvolution.pdf

于 2012-11-17T21:36:25.930 回答
1

首先,这似乎是一个非常混乱的情况,我认为没有“干净”的解决方案。我经历过几次类似的情况——它们并不好玩。

首先,更改您的客户端应用程序的工作将非常重要 - 如果基础域发生变化(例如,通过引入与人分开的地址的概念),客户端应用程序也会发生变化 - 这不仅仅是变化以您访问数据的方式。避免这种痛苦的最好方法是编写 API 层以反映未来的业务领域模型,并将旧的数据库模式粘合到其中;如果有新概念您无法使用旧数据反映(例如“get /app/addresses/addressID”),则抛出 NotImplemented 错误。在哪里可以用旧数据反映新模型,尽可能将它们连接在一起,然后在幕后重新考虑。

其次,这意味着您需要将版本控制作为首要关注点构建到您的 API 中——因此您可以告诉客户在版本 1 中,功能 x、y 和 z 会引发“未实现”异常。每个版本都应该向后兼容,但会添加新功能。这样,只要不破坏服务,您就可以重构版本 1 中的功能,并在版本 1.1 中实现功能 x,在版本 1.2 中实现功能 y 等。理想情况下,为您的版本制定路线图,并通知客户端应用程序如果您要停止支持某个版本或发布重大更改,请拥有所有者。

第三,为您的 API 进行一组自动化集成测试是您可以做出的最佳投资——它们确认您在重构时没有破坏功能。

希望这有一些用处 - 我认为您的问题没有一个单一、直接的答案。

于 2012-11-27T15:37:34.117 回答