question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Set aurora_replica_read_consistency to "session" before DML commands .Net6.0 + EFCore6 + Pomelo6 + AWS Aurora (MySQL 5.7)

See original GitHub issue

The issue

I am using AWS Aurora MySQL. Following below article, I have created a secondary readonly cluster and enabled write-forwarding on it so that all write queries sent to secondary readonly cluster are forwarded to primary cluster.

https://aws.amazon.com/blogs/database/building-globally-distributed-mysql-applications-using-write-forwarding-in-amazon-aurora-global-database/

As mentioned in above post, it also requires to set parameter aurora_replica_read_consistency at session level. And I’ve set this in the init_connect like this: set @@aurora_replica_read_consistency=SESSION … so that it gets executed automatically when new client connects.

When testing write-queries in MySQL Workbench, it works perfectly and no additional change is required. The same behavior was expected in our .net6.0 application. However, when issuing a write-query in .net6.0 application using Pomelo 6.0.1, it throws an error as if aurora_replica_read_consistency is set to blank.

Exception message:
Stack trace: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
 ---> MySqlConnector.MySqlException (0x80004005): The MySQL server is running with the --read-only option so it cannot execute this statement
   at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in /_/src/MySqlConnector/Core/ServerSession.cs:line 954
   at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 44
   at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 127
   at MySqlConnector.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 456
   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 56
   at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 330
   at MySqlConnector.MySqlCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 323
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass33_0`2.<<ExecuteAsync>b__0>d.MoveNext()

Do we need additional changes when using write-forward on AWS Aurora MySQL with Pomelo?

Further technical details

MySQL version: 5.7.12-log Operating system: AWS RDS Aurora Pomelo.EntityFrameworkCore.MySql version: 6.0.1 Microsoft.AspNetCore.App version:

Other details about my project setup: TargetFramework: .net6.0 WebAPI Project

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:33

github_iconTop GitHub Comments

2reactions
bgraingercommented, Dec 2, 2022

Note that you will need to disable SSL with SslMode=None; for the packet capture to be useful. If that’s not possible (e.g., can’t be disabled on Aurora) then all the packets will be encrypted and I won’t be able to read them to see what’s going on.

2reactions
bgraingercommented, Nov 29, 2022

Oddly, the first connection that gets created executes this query and gets back a result of SESSION, but subsequent connections execute the same query but get a blank result. Any idea why that would happen? Why would the init_connect SQL only get applied to the first connection created, but not the subsequent ones?

My guess would be connection pooling. MySqlConnection.Open doesn’t always result in a new connection being established to the database server (for performance). Most of the time, an existing connection is reused. Moreover, that connection is reset (to clear session variables, temp tables, etc.). My guess would be that in Aurora, this also clears the aurora_replica_read_consistency setting.

You could test this theory by adding Connection Reset = false; to your connection string.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Setting up replication with MySQL or another Aurora DB ...
You can set up replication where your Aurora MySQL DB cluster is the replication source or the replica. You can replicate with an...
Read more >
Best practices with Amazon Aurora MySQL
This topic includes information on best practices and options for using or migrating data to an Amazon Aurora MySQL DB cluster.
Read more >
Using write forwarding in an Amazon Aurora global database
Learn how to use write forwarding with Aurora MySQL-based global databases to send write operations from a secondary AWS Region to the primary...
Read more >
Working with parallel query for Amazon Aurora MySQL
Aurora MySQL parallel query is an optimization that parallelizes some of the I/O and computation involved in processing data-intensive queries.
Read more >
Replication with Amazon Aurora MySQL
You can use the SET TRANSACTION ISOLATION LEVEL command to change the transaction level only for the primary instance of an Aurora MySQL...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found