Pomelo.EntityFrameworkCore.MySql icon indicating copy to clipboard operation
Pomelo.EntityFrameworkCore.MySql copied to clipboard

Database Transaction is broken after Socket Exception (10054)

Open Palam7348 opened this issue 2 years ago • 0 comments

Steps to reproduce

The issue doesn't have exact steps to reproduce.

public async Task<T> ExecuteAsync<T>(Func<Task<T>> action)
        {
            IExecutionStrategy strategy = _context.Database.CreateExecutionStrategy();

            return await strategy.ExecuteAsync(async () =>
            {
                await using IDbContextTransaction transaction = await _context.Database.BeginTransactionAsync();

                try
                {
                    T result = await action(); // action contains some code which is communicating with database

                    await transaction.CommitAsync();

                    return result;
                }
                catch
                {
                    await transaction.RollbackAsync(); // throws System.ObjectDisposedException: Cannot access a disposed object.Object name: 'MySqlTransaction'.
                    throw;
                }
            });
        }

Also, retry is enabled for the DB Context: options.EnableRetryOnFailure(5, TimeSpan.FromSeconds(3), null);

The issue

The issue takes place if one of the queries to a DB within a transaction is failed due to "System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host."

Then all the following requests to database are failed with the following error: "System.InvalidOperationException: The transaction associated with this command is not the connection's active transaction; see https://fl.vu/mysql-trans"

And when I try to roll back the transaction it throws "System.ObjectDisposedException: Cannot access a disposed object. Object name: 'MySqlTransaction'."

Expected behavior: If a Socket exception has occurred, then the failed request should be retried according to the retry strategy settings and also, DB transaction should not be broken or disposed

StackTrace:

ERROR 2023-02-16 00:40:18,818 Microsoft.EntityFrameworkCore.Query [106] - An exception occurred while iterating over the results of a query for context type 'TestApp.Infrastructure.PersistenceTestDbContext'.
System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
   at MySqlConnector.Protocol.Serialization.SocketByteHandler.WriteBytesAsync(ReadOnlyMemory`1 data, IOBehavior ioBehavior) in /_/src/MySqlConnector/Protocol/Serialization/SocketByteHandler.cs:line 125
--- End of stack trace from previous location ---
   at MySqlConnector.Protocol.Serialization.ProtocolUtility.<WritePacketAsync>g__WritePacketAsyncAwaited|8_0(ValueTask`1 task, Byte[] buffer) in /_/src/MySqlConnector/Protocol/Serialization/ProtocolUtility.cs:line 546
   at MySqlConnector.Core.ServerSession.SendReplyAsyncAwaited(ValueTask`1 task) in /_/src/MySqlConnector/Core/ServerSession.cs:line 987
   at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 55
   at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
   at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
   at MySqlConnector.Protocol.Serialization.SocketByteHandler.WriteBytesAsync(ReadOnlyMemory`1 data, IOBehavior ioBehavior) in /_/src/MySqlConnector/Protocol/Serialization/SocketByteHandler.cs:line 125
--- End of stack trace from previous location ---
   at MySqlConnector.Protocol.Serialization.ProtocolUtility.<WritePacketAsync>g__WritePacketAsyncAwaited|8_0(ValueTask`1 task, Byte[] buffer) in /_/src/MySqlConnector/Protocol/Serialization/ProtocolUtility.cs:line 546
   at MySqlConnector.Core.ServerSession.SendReplyAsyncAwaited(ValueTask`1 task) in /_/src/MySqlConnector/Core/ServerSession.cs:line 987
   at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 55
   at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
   at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()

ERROR 2023-02-16 00:40:18,821 My Test Service [106] - Error occurs on saving entity: An existing connection was forcibly closed by the remote host.
INFO  2023-02-16 00:40:18,821 My Test Service [106] - Execute another query
ERROR 2023-02-16 00:40:18,833 Microsoft.EntityFrameworkCore.Database.Command [106] - Failed executing DbCommand (0ms) ERROR 2023-02-16 00:40:18,834 Microsoft.EntityFrameworkCore.Query [106] - An exception occurred while iterating over the results of a query for context type 'Test.Infrastructure.Persistence.TestDbContext'.
System.InvalidOperationException: The transaction associated with this command is not the connection's active transaction; see https://fl.vu/mysql-trans
   at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
   at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() System.InvalidOperationException: The transaction associated with this command is not the connection's active transaction; see https://fl.vu/mysql-trans
   at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
   at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()

ERROR 2023-02-16 00:40:18,839 Microsoft.EntityFrameworkCore.Database.Transaction [106] - An error occurred using a transaction. 
ERROR 2023-02-16 00:40:18,841 My Test Service [106] - Error occurred: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'MySqlTransaction'.
   at MySqlConnector.MySqlTransaction.VerifyValid() in /_/src/MySqlConnector/MySqlTransaction.cs:line 281
   at MySqlConnector.MySqlTransaction.RollbackAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlTransaction.cs:line 66
   at Microsoft.EntityFrameworkCore.Storage.RelationalTransaction.RollbackAsync(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalTransaction.RollbackAsync(CancellationToken cancellationToken)
   at Test.Infrastructure.Persistence.Services.TransactionService.<>c__DisplayClass3_0`1.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Test.Infrastructure.Persistence.Services.TransactionService.<>c__DisplayClass3_0`1.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass33_0`2.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Test.Infrastructure.Persistence.Services.TransactionService.ExecuteAsync[T](Func`1 action)
   at Test.Domain.Core.Services.EntityN.AddEntity.MyService.AddEntity(Type1 a, Type2 b) 

Further technical details

MariaDB version: 10.4 Operating system: Windows 10 Pomelo.EntityFrameworkCore.MySql version: 6.0.1

Palam7348 avatar Feb 17 '23 10:02 Palam7348