有时,我们必须在一个项目中使用多个数据库,目的是:
有很多关于第一宗案件的讨论,但我没有发现关于第二宗案件的任何消息
示例1:为了解决基于组织图的组织访问的复杂性,我们使用了图形数据库(如neo4j )。
示例2:我们希望使某些系统表单(实体)具有动态,并允许用户向其添加新字段并将这些附加值存储在nosql中。
考虑到大多数用例在事务上更好,我们使用工作单元,但是这种模式与几个数据库不兼容。
我想到的主要解决方案是使用SQL数据库作为主数据库,而其他数据库将数据存储为阴影(或数据的投影),并始终与主SQL数据库同步(与发件模式和事件同步)。
我再次强调,这个影子数据不是用来读取模型的,它对程序的写端(业务逻辑)有影响。
谢谢
更新:完整示例
假设我们有一个系统,它使用发件箱模式来确保事件被发送,并且在工作单元结束时,它们被提交。
组织结构图数据应该在neo4j内部。
也就是说,执行了AddChartUseCase
,它必须将数据保存在neo4j中,事件必须保存在发件箱(ChartCreatedEvent
)中。
如何有一个工作单元来管理两个数据库之间的事务(我认为答案是:不可能)
发布于 2023-05-30 07:11:01
“工作单位”不一定与多个数据库不兼容。它与不同的服务/进程不兼容,其中每个服务都有自己的存储系统。
在一个服务中,一个UoW理论上可以容纳两个或多个不同的数据库上下文,在两个服务上执行一个组合事务,并在另一个数据库的提交操作失败时管理对另一个数据库的手动回滚。然而,这意味着您将同时使用两个数据库并同步使用一个服务,这可以很容易地引入缩放问题。
由于您提到了事务发件箱模式,我认为您所想到的体系结构看起来是不同的:每个数据库都由不同的(微?)控制。服务,这意味着您需要分布式事务。“发件箱”是实现此功能的一种常见方式,它将业务事务分成两个或多个技术事务,每个服务至少有一个。
这样,您就可以使用UoW来
然后,依赖服务将从发件箱中获得由消息中继和消息代理生成的事件,并必须相应地解释有效负载。也许为了解释事件,他们必须自己创建一个UoW,这将取决于总体的复杂性。在最坏的情况下,这里的失败事务需要生成一个事件来再次回滚第一个事务(但这与情况有关,当您的不同数据库在这种程度上相互交织时,您可能会重新考虑将数据拆分到不同DBMS中的选择)。
TLDR;UoW是一个服务的实现细节,当您的数据库处于不同服务的控制之下,并且您的业务事务跨越多个服务时,一个UoW就不足以实现一个业务事务。
发布于 2023-05-31 02:01:26
除了@DocBrown的答案。
请允许我再“快一点”一点。
如何有一个工作单元来管理两个数据库之间的事务(我认为答案是:不可能)
如果您询问如何将两个数据源的事务链接到一个单独的按酸方向的事务,则答案是分布式事务。坏消息是,实施起来并不容易。至少还不够简单,无法从UoW中完成。
分布式事务也很难实现,因为并非所有数据源都支持这些事务。如果没有,则需要一个自定义实现。自定义实现有两种形式:中间件(例如应用服务器)或自定义事务管理器(例如库)。在这两种情况下,UoW都会请求与这个新的“层”建立新的连接,并将其操作为一个常规DB事务。在幕后,事务管理器/中间件完成所有困难的工作。
如果要实现自定义事务管理器,考虑到事务的短暂性,两阶段提交算法看起来是一个很好的起点。
现在请记住以下几点:不能假设所有数据源都实现ACID事务。希望您的数据库能够打开连接、创建事务、保存(提交)数据或对称地还原更改(rollback),但是如果其中一个数据库不支持回滚或ACID事务,则必须向事务管理器提供自定义故障转移策略。例如,当不支持回滚时,事务管理器必须执行补偿事务。这些事务也需要事务管理..。正如您可能猜到的,编码不是一件琐碎的事情。
https://softwareengineering.stackexchange.com/questions/445786
复制