Skip to main content

How to Make EnableRetryOnFailure Retry MySQL Errors in EF Core

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

EnableRetryOnFailure looks like a switch, and with Oracle's MySQL provider, it isn't one: until you list error numbers, it retries nothing. Here's the list I use, how to confirm it's working, and how long a request can wait.

Prerequisites​

  • A .NET C# project using MySql.EntityFrameworkCore. I used 10.0.12, with EF Core 10.0.14 and MySQL 9.7.4. Part 1 of the series sets one up.

Step 1: List the Numbers​

src/Dewiride.Inventory.Data/InventoryDataServiceCollectionExtensions.cs (excerpt)
options.UseMySQL(connectionString, mySql =>
{
mySql.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(5),
errorNumbersToAdd: [0, 1040, 1042, 1053, 1213]);
});
NumberErrorWhen it happens
1213Deadlock found when trying to get lockMySQL picked your transaction to undo
1042Unable to connect to any of the specified MySQL hostsMySQL is down
1053Server shutdown in progressMySQL is stopping
1040Too many connectionsNo free connections
0The driver's own errorA dropped connection, and also a full pool

Leave out 1205, the lock wait timeout. Each retry would wait the whole limit again.

Step 2: Check It's Working​

Two requests that update the same two products in opposite orders will deadlock. The log shows the retry:

API log
Attempt 1
Attempt 1
A transient exception occurred during execution. The operation will be retried after 0ms.
Attempt 2
Output (the two requests)
{"attempts":1}
200
{"attempts":2}
200

Both requests answering 200, one after two attempts, with the log line A transient exception occurred during execution. The operation will be retried after 0ms.

A transient exception occurred during execution. is the line to look for. It's logged at Information, under Microsoft.EntityFrameworkCore.Infrastructure.

Step 3: Know How Long It Waits​

With MySQL stopped, and 3 retries:

Output (status, and how long it took)
500 4.734215s
API log
A transient exception occurred during execution. The operation will be retried after 0ms.
A transient exception occurred during execution. The operation will be retried after 1045ms.
A transient exception occurred during execution. The operation will be retried after 3124ms.

The delays grow, with a little randomness, up to maxRetryDelay. So 3 retries cover about 4 seconds of outage. After that, you get RetryLimitExceededException.

Step 4: Know What This Doesn't Do​

A custom execution strategy solves the last two in about 20 lines.

Common Mistakes​

MistakeWhat happensDo this instead
errorNumbersToAdd: []No retries, and no warningList them
EnableRetryOnFailure() with nothing elseThe sameList them
Raising maxRetryCount to 50Requests hang for minutesKeep it small, and answer 503

Troubleshooting​

SymptomLikely causeFix
No will be retried lineThe number isn't listed, or the log level hides itCheck both
does not support user-initiated transactionsA transaction outside the strategyThe fix
One order became twoThe first attempt committedThe fix

Conclusion​

With Oracle's provider, retries start only when you list the numbers. List 1213, 1042, 1053, 1040 and 0, look for will be retried in the log, and remember that it's only safe if a repeat is safe.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.