Skip to content

Failover plugin causes 'MySqlConnection is already in use' with EF Core / Pomelo MySqlConnector #268

@adomass

Description

@adomass

Description

When using the failover plugin with Entity Framework Core (Pomelo.EntityFrameworkCore.MySql 9.0.0) and MySqlConnector, an Aurora writer failover causes the connection to enter a permanently broken state. After the first successful reconnection, all subsequent commands fail with MySqlConnection is already in use.

Environment

  • AWS.AdvancedDotnetDataProviderWrapper.EntityFrameworkCore.MySqlConnector 1.0.1
  • Pomelo.EntityFrameworkCore.MySql 9.0.0
  • MySqlConnector 2.4.0 (transitive via Pomelo)
  • .NET 10.0
  • Aurora MySQL cluster (eu-west-1, 2 writer-eligible instances)

Steps to Reproduce

  1. Configure EF Core with the wrapper:
optionsBuilder.UseAwsWrapper(
    connectionString + ";Plugins=failover;",
    wrappedOptions => wrappedOptions.UseMySql(connectionString, serverVersion));
  1. Execute write queries continuously via DbContext.Database.ExecuteSqlRawAsync()

  2. Trigger Aurora failover: aws rds failover-db-cluster --db-cluster-identifier <cluster>

  3. Observe behavior

Observed Behavior

  1. Queries 1-14: succeed (before failover)
  2. Query 15: fails with connection error (failover starts) — DealWithOriginalExceptionAsync fires
  3. Queries 16-17: connection errors (expected during failover)
  4. Queries 18-26: succeed (wrapper reconnected to new writer — failover worked!)
  5. Query 27+: ALL fail permanently with MySqlConnection is already in use

The wrapper successfully reconnects once, but then the underlying MySqlConnection's ServerSession gets stuck in State.Querying — every subsequent command hits StartQuerying() which throws because the session state was never reset.

Root Cause Analysis

The failover plugin calls SetCurrentConnection() to swap the underlying DbConnection to a new one pointing at the new writer. However:

  1. EF Core's RelationalConnection caches a reference to the original DbConnection
  2. When the failover plugin swaps the connection, the old MySqlConnection's ServerSession.m_state remains Querying
  3. The wrapper's AwsWrapperConnection has ActiveWrapperCommands list — commands from the failed connection may not be properly unregistered
  4. Subsequent commands attempt to execute on the old MySqlConnection reference (cached by EF Core), which has a session stuck in Querying state

The MySqlConnection is already in use check is in MySqlConnector.Core.ServerSession.StartQuerying():

if (m_state is State.Querying or State.CancelingQuery)
    throw new InvalidOperationException("This MySqlConnection is already in use.");

Additional Issues Found

During investigation we also found:

  1. initialConnection plugin breaks EF Core migrations — it swaps the connection mid-migration transaction, causing DDL to auto-commit but __EFMigrationsHistory INSERT to be lost (tables created but not recorded)

  2. EnableRetryOnFailure conflicts with failover plugin — EF Core's retry strategy tries to reuse the connection during DealWithOriginalExceptionAsync, causing the same "already in use" error immediately

  3. Plugins= connection string key rejected by MySqlConnectorMySqlConnectionStringBuilder throws ArgumentException: Option 'plugins' not supported. The wrapper and EF Core need separate connection strings.

  4. Allow User Variables=true required — the wrapper re-parses SQL through AwsWrapperCommand, causing MySqlConnector to treat @ user variables in stored procedure DDL as parameters

Expected Behavior

After a successful failover reconnection, subsequent commands should execute normally against the new writer without connection state corruption.

Workaround

Currently there is no workaround for the failover plugin with EF Core. Using only the initialConnection plugin (without failover) works for reader load balancing but provides no failover handling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions