1

MDriven 为多个对象生成相同的 ECO_ID 似乎存在问题。在大多数情况下,它似乎与意外的进程关闭和/或服务器关闭一起发生,但它也确实发生在正常活动期间。

我们的系统由一个 ASP.NET 应用程序和一个 WinForms 应用程序组成。ASP.NET 应用程序在 IIS 中设置为使用单个工作进程。我们混合了 WebForms 和 MVC,包括 ApiControllers。我们使用的是相当旧的 ECO 包版本:7.0.0.10021。我们在 VS 2017 上,目标框架是 4.7.1。

我们将其配置为使用 64 位整数作为对象 id:s。数据库是火鸟。SQL 配置设置为使用 ReadCommitted 事务隔离。

据我所知,我们已经配置EcoSpaceStrategyHandlerEcoSpaceStrategyHandler.SessionStateMode.Never,这应该意味着 EcoSpaces 根本没有被重用,对吧?(为什么我什至会EcoSpaceStrategyHandler在这种情况下使用,而不是使用new关键字正常创建 EcoSpace?)

我们已经创建了用于所有控制器的类MasterController : ControllerMasterApiController : ApiController这些具有EcoSpace简单地执行此操作的属性:

if (ecoSpace == null)
{
    if (ecoSpaceStrategyHandler == null)
        ecoSpaceStrategyHandler = new EcoSpaceStrategyHandler(
            EcoSpaceStrategyHandler.SessionStateMode.Never,
            typeof(DiamondsEcoSpace),
            null,
            false
        );
    ecoSpace = (DiamondsEcoSpace)ecoSpaceStrategyHandler.GetEcoSpace();
}
return ecoSpace;

即,如果没有创建策略处理程序,则创建一个指定生态空间不进行池化和会话状态持久化的处理程序。然后,如果没有获取生态空间,则从策略处理程序获取一个。返回生态空间。这是一种可接受的方法吗?为什么会比简单地这样做更好:

if (ecoSpace = null)
    ecoSpace = new DiamondsEcoSpace();
return ecoSpace;

在 aspx 中,我们有一个母版页,其中包含EcoSpaceManager. 它已被配置为使用一个池,但SessionStateMode它是Never. 它已EnableViewState设置为true。这可以接受吗?这是否意味着 EcoSpaces 将在往返之间汇集但停用?

我们可能会连续收到多个传入的 API 调用,因此一个 API 调用在下一个调用之前尚未完成。我假设这意味着多个实例MasterApiController可以同时执行但在不同的线程中。当然也可能有MasterController执行 MVC 请求的实例,并且 WinForms 应用程序可能正在运行一些批处理作业或其他。

但据我了解,id 预订是在任何UpdateDatabase通话开始时进行的,方式如下:

update "ECO_ID" set "BOLD_ID" = "BOLD_ID" + :N;
select "BOLD_ID" from "ECO_ID";

如果返回值为 K,这将保留 N 个新的 id:s,范围从 K-N 到 K-1。在任何地方使用 ReadCommitted 事务应确保更新锁定 id 数据行,强制所有并发保存操作等待,然后获取在不受其他事务干扰的情况下更新结果,然后提交。此时,任何其他挂起的保存操作都可以继续进行自己的 id 保留。我看不出这会如何导致多个对象使用相同的 ID。

我应该注意到,它似乎有时会在一个单独的 UpdateDatabase 中产生 id 重复,即当保存一组新的相关对象时,其中一些最终具有相同的 id。我还没有真正证实这一点。

有什么想法可能会在这里发生吗?我应该寻找什么?

4

1 回答 1

1

该问题很可能是您使用了 ReadCommitted 隔离。这允许 2 个系统同时启动一个事务,读取当前值,增加批次,然后相互保存。

您必须使用 Serializable 隔离来生成密钥;即只读取当前不在写操作中的东西。

MDriven 对隔离级别 UpdateIsolationLevel 和 FetchIsolationLevel 使用 2 个设置。

将 UpdateIsolationLevel 设置为 Serializable

于 2021-12-06T09:08:06.023 回答