You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ASP.NET MVC控制器会导致IIS中AppPool挂起?

多请求下EF6查询MySQL挂起问题排查

环境

  • C# ASP.NET MVC 5
  • Entity Framework 6
  • .NET Framework 4.8
  • MySQL
  • IIS

问题现象

执行以下代码时,日志仅输出set AppAgent start,无set AppAgent end,说明数据库查询环节无异常但出现挂起:

LogErr("set AppAgent start");

_AppWebsite = db.Websites
                .Where(x => x.Domain == Request.Url.Host)
                .SingleOrDefault();
LogErr("set AppAgent end");

复现场景

  • 站点发布后发起多请求时易触发挂起
  • 站点运行稳定后难以复现
  • 重启IIS应用池可恢复

相关背景

  • 代码位于自定义BaseController的OnActionExecuting方法中,通过调用AppWebsite属性触发上述查询
  • 曾尝试将代码移至Initialize方法,问题未解决

涉及表结构(websites表,共5条记录)

CREATE TABLE `websites` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `SellerId` int NOT NULL,
  `Name` varchar(45) NOT NULL,
  `Domain` varchar(50) DEFAULT NULL,
  `MenuH` varchar(150) DEFAULT '',
  `MenuF` varchar(150) DEFAULT '',
  `CreatedDate` datetime DEFAULT NULL,
  `DeletedDate` datetime DEFAULT NULL,
  `SubEndDate` date DEFAULT '2090-01-01',
  `Logo` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `i_SellerId` (`SellerId`),
  KEY `i_Domain` (`Domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

排查与解决方案

1. 确保DbContext线程安全

EF6的DbContext不是线程安全的,多请求并发时共享实例会直接导致挂起、死锁。

  • 每个请求使用独立的DbContext实例:在BaseController构造函数中初始化,或通过依赖注入框架(如Autofac)将其生命周期配置为每请求一个实例。

2. 优化数据库连接与查询超时

  • 在连接字符串中添加连接超时配置,避免无限等待:
    <connectionStrings>
      <add name="YourDbContext" connectionString="server=xxx;database=xxx;uid=xxx;pwd=xxx;Connect Timeout=15;" providerName="MySql.Data.MySqlClient" />
    </connectionStrings>
    
  • 给EF查询设置命令超时,强制中断长时间挂起的请求:
    db.Database.CommandTimeout = 10; // 设置10秒超时
    _AppWebsite = db.Websites
                    .Where(x => x.Domain == Request.Url.Host)
                    .SingleOrDefault();
    

3. 调整数据库连接池参数

多请求并发时连接池耗尽会导致请求等待:

  • 在连接字符串中增加连接池配置:
    <add name="YourDbContext" connectionString="...;Max Pool Size=100;Min Pool Size=5;" />
    
  • 确保DbContext被正确释放,避免连接泄漏:
    protected override void Dispose(bool disposing)
    {
        if (disposing && db != null)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }
    

4. 排查MySQL锁阻塞

InnoDB的行锁/表锁可能导致查询阻塞:

  • 执行SHOW ENGINE INNODB STATUS;查看锁等待日志
  • 用EXPLAIN分析查询计划,确认索引生效:
    EXPLAIN SELECT * FROM websites WHERE Domain = '测试域名';
    

5. 缓存网站信息减少数据库查询

避免每个请求都触发数据库查询,用MemoryCache缓存结果:

private Website _appWebsite;
public Website AppWebsite
{
    get
    {
        if (_appWebsite == null)
        {
            var cacheKey = $"Website_{Request.Url.Host}";
            _appWebsite = MemoryCache.Default.Get(cacheKey) as Website;
            if (_appWebsite == null)
            {
                _appWebsite = db.Websites.Where(x => x.Domain == Request.Url.Host).SingleOrDefault();
                MemoryCache.Default.Add(cacheKey, _appWebsite, DateTimeOffset.Now.AddHours(1));
            }
        }
        return _appWebsite;
    }
}

内容的提问来源于stack exchange,提问作者EamonnM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:30:13