【问题标题】:Azure SQL DB hanging on to connection until EF times outAzure SQL DB 一直挂在连接上,直到 EF 超时
【发布时间】:2021-12-13 19:48:39
【问题描述】:

我有一个间歇性问题,我似乎无法深入了解 .NET Framework 4.6 MVC API (C#) 使用需要很长时间的 Entity Framework 6(运行时 v4.0.30319)存储过程调用回应。

存储过程托管在 Azure SQL DB 上。

这是一个不起眼的过程,它会询问几张表格,为营养师提供他们客户的最新数据和网站互动。

ALTER PROCEDURE [PORTAL].[GetNutritionistCustomers]

    @id_usernut varchar(20)

AS

    WITH Activity AS (
        SELECT LastActivity = MAX(ExecutionDate),
               ded.UserName
        FROM portal.DailyExecutionData ded
        WHERE ded.ExecutionDate < GETDATE()
        GROUP BY ded.UserName
    ),
    Logging AS (
        SELECT LastLogin = MAX(l.LoggedOnDate),
               l.UserName
        FROM PORTAL.Logins l
        WHERE l.LoginType = 'Direct Client'
        GROUP BY l.UserName
    )
    SELECT unc.CompanyCode,
           a.ACCOUNT,
           ad.ADDRESS1,
           un.ID_UserNut,
           ueu.ExpirationDate,
           Expired = CAST(CASE WHEN ueu.ExpirationDate < GETDATE() THEN 1 ELSE 0 END AS BIT),
           LastActive = la.LastActivity,
           l.LastLogin
    FROM UK_Nutritionist un
    JOIN UK_NutCompany unc ON un.ID_UserNut = unc.ID_UserNut
    JOIN UK_EnabledUsers ueu ON unc.CompanyCode = ueu.UserName
    JOIN Klogix.ACCOUNT a ON ueu.ID_User = a.ACCOUNTID
    LEFT JOIN Klogix.ADDRESS ad ON a.ADDRESSID = ad.ADDRESSID AND ad.IsPrimary = 1
    LEFT JOIN Activity la ON ueu.UserName = la.UserName
    LEFT JOIN Logging l ON ueu.UserName = l.UserName
    WHERE un.ID_UserNut = @id_usernut

在 SSMS 或 ADS 中运行此过程平均需要大约 50-100 毫秒才能完成。这是一致的,表的索引很好,查询计划是所有的索引搜索。没有 Key 或 RID 查找危险信号。

在使用探查器进行调查后,我确定发生的情况是 EF 创建了一个连接,调用了该过程。我可以看到 RPC 进入了,EF 达到了连接超时时间,然后我们得到 RPC 完成,数据返回给 EF,代码旋转出一个 pocs 列表以 json 形式返回给调用者。

[HttpGet]
[Route("Customers")]
public HttpResponseMessage Get()
{
    try
    {
        if (IsTokenInvalid(Request))
            return Request.CreateResponse(HttpStatusCode.Unauthorized);

        var nutritionistCustomers = new ExcdbEntities().GetNutritionistCustomers(TokenPayload.Nutritionist).Select(x => new NutritionistCustomers()
        {
            Account = x.ACCOUNT,
            Address = x.ADDRESS1,
            CompanyCode = x.CompanyCode,
            ExpirationDate = x.ExpirationDate,
            expired = x.Expired,
            LastActive = x.LastActive,
            LastLogin = x.LastLogin
            
        }).ToList();
        return Request.CreateResponse(HttpStatusCode.OK, GenerateResponse(nutritionistCustomers))
    }
    catch (Exception e)
    {
        return Request.CreateResponse(HttpStatusCode.InternalServerError, GenerateResponse(e));
    }
}

如果我更改了连接的超时时间,那么 SQL 在释放数据之前等待的时间会更改。

我认为这可能与托管 API 的 Azure 应用服务有关,但事实证明,在 Visual Studio 的调试中运行它也有同样的问题。

短期修复是重新编译存储过程。这将立即返回数据。但在未来某个不确定的时间点,同样的程序会突然再次表现出这种行为。

只有这个过程才能做到这一点,所有其他 EF 交互,无论是 linq 到 sql 表还是视图询问,以及所有其他过程似乎都表现良好。 这种情况以前在具有相同架构的旧系统中发生过,尽管它是不同数据库上的不同过程。

虽然缩短超时是一种解决方法,但它是一个系统范围的值,即使是 10 秒,足以应对系统故障,对于这个应该是即时的客户选择屏幕来说也太长了。 另外,如果有人知道可能发生了什么,我宁愿解决根本问题。

我已经考虑过在语句中使用 OPTION_RECOMPILE,但这样做感觉不对。

如果其他人经历过这种情况并有任何见解,我将不胜感激,因为它让我分心。

【问题讨论】:

  • 我在 SSMS 调用中添加了从分析器中删除的 EF 上下文设置。我认为重要的是:set transaction isolation level read committed 当它出现问题时,我会在 SSMS 中收到未提交的事务警告,我认为这就是等待锁解决的问题。我不确定是什么原因造成的,也许是 ADF 管道的问题? Anyhoo,我已在 proc 本身的编译上下文中将事务隔离级别读取设置为未提交。哈基,但它的伎俩。现在我需要调查真正的原因。

标签: c# sql-server azure entity-framework stored-procedures


【解决方案1】:

最终证明这是一个串联问题。 EF 在其上下文中将 CONCAT_NULL_YIELDS_NULL 设置为关闭,无论出于何种原因,这都会导致真正可怕的性能问题。

对于我只能称之为前任员工无能的遗留问题,程序返回的日期对日期的各个日期部分进行了一些莫名其妙的分割和连接。

你知道,我将它替换为返回日期(并且显然修改了 EF 对象),嘿,没有更多的性能问题。

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 2022-01-12
    • 2019-05-21
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 2015-09-08
    相关资源
    最近更新 更多