我们已经开始使用NuGet的Microsoft.AspNet.Providers.Core包中提供的更新的System.Web.Providers.我们开始迁移现有用户,发现性能下降,然后发生死锁.这个用户少于30,000(远远低于我们需要创建的1,000,000+用户).当我们调用提供程序时,它来自每个服务器上的多个线程,并且有多个服务器运行此相同的进程.这是为了能够尽快创建我们所需的所有用户,并模拟我们期望在其上线时看到的负载.
SQL Server为死锁生成的日志包含以下EF生成的sql:
SELECT
[Limit1].[UserId] AS [UserId]
, [Limit1].[ApplicationId] AS [ApplicationId]
, [Limit1].[UserName] AS [UserName]
, [Limit1].[IsAnonymous] AS [IsAnonymous]
, [Limit1].[LastActivityDate] AS [LastActivityDate]
FROM
(SELECT TOP (1)
[Extent1].[UserId] AS [UserId]
, [Extent1].[ApplicationId] AS [ApplicationId]
, [Extent1].[UserName] AS [UserName]
, [Extent1].[IsAnonymous] AS [IsAnonymous]
, [Extent1].[LastActivityDate] AS [LastActivityDate]
FROM
[dbo].[Users] AS [Extent1]
INNER JOIN [dbo].[Applications] AS [Extent2] ON [Extent1].[ApplicationId] = [Extent2].[ApplicationId]
WHERE
((LOWER([Extent2].[ApplicationName])) = (LOWER(@p__linq__0)))
AND ((LOWER([Extent1].[UserName])) = (LOWER(@p__linq__1)))
) AS [Limit1]
Run Code Online (Sandbox Code Playgroud)
我们手动运行查询,执行计划表示它正在执行表扫描,即使存在基础索引.原因是使用LOWER([Extent1].[UserName]).
我们查看了提供程序代码,看看我们是否做错了什么,或者是否有办法拦截或替换数据库访问代码.我们没有看到任何选项来执行此操作,但我们确实找到了LOWER问题的根源,.ToLower()正在调用列和参数.
return (from …Run Code Online (Sandbox Code Playgroud)