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

EntityFrameworkCore+MySQL在Ubuntu/Linux下Min Pool Size>0时挂起

问题:.NET + MySQL连接池最小配置在Ubuntu环境下挂起

我使用.NET 8.0(也测试过.NET 6.0),搭配最新版EntityFrameworkCore、Pomelo.EntityFrameworkCore.MySql(也试过MySql.EntityFrameworkCore),MySQL版本为8.0.35(Docker部署和主机安装版都测过)。连接字符串里配置了Min Pool Size=10,应用在各类Windows环境(本地机器、Windows上的Ubuntu虚拟机、Windows上的Docker Compose、Azure平台)运行正常,但在Ubuntu 22.04物理机或Ubuntu 22.04上的Docker Compose环境中,建立数据库连接时会挂起。

移除Min Pool Size=10后,所有环境都能正常运行。哪怕延长连接超时时间,只要Min Pool Size>0,应用依然卡顿。

抛出的异常

app  | Unhandled exception. System.AggregateException: One or more errors occurred. (Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.)
app  |  ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
app  |  ---> System.TimeoutException: The operation has timed out.
app  |    at MySql.Data.Common.StreamCreator.<>c.<GetTcpStreamAsync>b__8_1()
app  |    at System.Threading.CancellationTokenSource.Invoke(Delegate d, Object state, CancellationTokenSource source)
app  |    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
app  | --- End of stack trace from previous location ---
app  |    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
app  |    at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
app  |    --- End of inner exception stack trace ---
app  |    at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
app  |    at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
app  |    at System.Threading.TimerQueue.FireNextTimers()
app  |    at System.Threading.ThreadPoolWorkQueue.Dispatch()
app  |    at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

复现代码

原始应用是ASP.NET Core API,已通过简易控制台应用复现问题:

主程序(Program.cs)

static async Task Main(string[] args)
{
    var envCnx = Environment.GetEnvironmentVariable("CONNECTION_STRING");

    IDbContextFactory dbContextFactory = new AppDbContextFactory(envCnx);

    using var db = await dbContextFactory.CreateDbContextAsync();

    await db.Database.MigrateAsync();

    var name = "User 1";

    if (!await db.Set<UserInfo>().AnyAsync(x => x.Name == name))
    {
        db.Add(new UserInfo() { Id = Guid.NewGuid(), Name = name, CreatedOn = DateTime.Now });

        await db.SaveChangesAsync();
    }
}

AppDbContextFactory

public interface IDbContextFactory : IDbContextFactory<DbContext>
{
}

public class AppDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>, IDbContextFactory<AppDbContext>, IDbContextFactory
{
    private readonly string _cnx;

    public AppDbContextFactory(string cnx)
    {
        _cnx = cnx;
    }

    public AppDbContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
        string cnx = args.Length > 0 ? args[0] : this._cnx;


#if DEBUG
        optionsBuilder.EnableSensitiveDataLogging();
        optionsBuilder.EnableDetailedErrors();
#endif
        optionsBuilder.UseMySql(cnx, ServerVersion.AutoDetect(cnx), mySqlOpts =>
        {
            mySqlOpts.UseNewtonsoftJson();
            mySqlOpts.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName);
        })
#if DEBUG
            .EnableSensitiveDataLogging()
            .EnableDetailedErrors()
#endif
        ;

        return new AppDbContext(optionsBuilder.Options);
    }

    public AppDbContext GetContext()
    {
        return CreateDbContext([_cnx]);
    }

    public AppDbContext CreateDbContext()
    {
        return GetContext();
    }

    DbContext IDbContextFactory<DbContext>.CreateDbContext()
    {
        return GetContext();
    }
}

AppDbContext

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<UserInfo>().HasKey(x => x.Id);
        modelBuilder.Entity<UserInfo>().HasIndex(x => x.Id).IsUnique();
        modelBuilder.Entity<UserInfo>().Property(t => t.Id).ValueGeneratedOnAdd();
        modelBuilder.Entity<UserInfo>().Property(x => x.Timestamp).IsRowVersion();
        modelBuilder.Entity<UserInfo>().HasIndex(x => x.Name);
        modelBuilder.Entity<UserInfo>().ToTable("users");
    }
}

UserInfo实体

public class UserInfo
{
    [JsonConstructor]
    public UserInfo() { }

    public Guid Id { get; set; }
    public string Name { get; set; }

    public DateTimeOffset CreatedOn { get; set; }

    public DateTime Timestamp { get; set; }
}

Docker配置

Dockerfile

#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base
USER app
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["ConsoleTestApp/ConsoleTestApp.csproj", "ConsoleTestApp/"]
RUN dotnet restore "./ConsoleTestApp/ConsoleTestApp.csproj"
COPY . .
WORKDIR "/src/ConsoleTestApp"
RUN dotnet build "./ConsoleTestApp.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./ConsoleTestApp.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ConsoleTestApp.dll"]

docker-compose.yml

version: "3.3"
name: "test-app"

services:

  app:
    image: console-app:latest
    container_name: console-app
    depends_on:
      - mysql
    environment:
      # CONNECTION_STRING: server=mysql,3306;user=root;password=2YSCK+fktPRGOi5omfRjCAP_am9+3r;database=test_db
      CONNECTION_STRING: server=mysql,3306;user=root;password=2YSCK+fktPRGOi5omfRjCAP_am9+3r;database=test_db;Min Pool Size=10;Connect Timeout=600

  mysql:
    container_name: db
    image: mysql:8.0.35
    cap_add:
      - SYS_NICE
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 2YSCK+fktPRGOi5omfRjCAP_am9+3r
      MYSQL_DATABASE: test_db

项目结构

.
├── ConsoleTestApp
│   ├── ConsoleTestApp.csproj
│   ├── Data
│   │   ├── AppDbContext.cs
│   │   ├── AppDbContextFactory.cs
│   │   ├── Migrations
│   │   │   ├── 20240523164903_InitialMigration.Designer.cs
│   │   │   ├── 20240523164903_InitialMigration.cs
│   │   │   └── AppDbContextModelSnapshot.cs
│   │   └── UserInfo.cs
│   ├── Program.cs
│   └── Properties
│       └── launchSettings.json
├── ConsoleTestApp.sln
├── Dockerfile
└── docker-compose.yml

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:43:09