ASP.NET C# MySQL 查询执行失败重试
ASP.NET C# MySQL query execution retry upon failure
是否有任何 ASP.NET package/DLL 允许 MySQL 查询执行失败时重试?
我已阅读有关 Transient Fault Handling and even came across a Dapper issue which shows an example 的内容,但根据我的研究,这仅适用于 SqlServer and/or Azure。
我的技术栈如下:
- .NET 4.5.2
- 小巧玲珑 1.50.2.0
- MySQL 5.6(使用 Amazon Aurora)
最终我正在尝试解决 sporadic failure issue 我相信实施一些重试逻辑将有助于缓解问题。
我尝试实现此 Dapper issue but because I am using MySql.Data 中的一些代码以连接到我的 MySql 数据库,它不适用于特定于 SqlServer 连接的各种方法。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Dapper;
using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
namespace TransientDapper
{
public static class TransientDapperExtensions
{
private static readonly RetryManager SqlRetryManager = GetDefaultRetryManager();
private static readonly RetryPolicy SqlCommandRetryPolicy = SqlRetryManager.GetDefaultSqlCommandRetryPolicy();
private static readonly RetryPolicy SqlConnectionRetryPolicy =
SqlRetryManager.GetDefaultSqlConnectionRetryPolicy();
private static RetryManager GetDefaultRetryManager()
{
const int retryCount = 4;
const int minBackoffDelayMilliseconds = 2000;
const int maxBackoffDelayMilliseconds = 8000;
const int deltaBackoffMilliseconds = 2000;
var exponentialBackoffStrategy =
new ExponentialBackoff(
"exponentialBackoffStrategy",
retryCount,
TimeSpan.FromMilliseconds(minBackoffDelayMilliseconds),
TimeSpan.FromMilliseconds(maxBackoffDelayMilliseconds),
TimeSpan.FromMilliseconds(deltaBackoffMilliseconds)
);
var manager = new RetryManager(
new List<RetryStrategy>
{
exponentialBackoffStrategy
},
exponentialBackoffStrategy.Name
);
return manager;
}
public static void OpenWithRetry(this SqlConnection cnn)
{
cnn.OpenWithRetry(SqlConnectionRetryPolicy);
}
public static IEnumerable<T> QueryWithRetry<T>(
this SqlConnection cnn, string sql, object param = null, IDbTransaction transaction = null,
bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
)
{
return SqlCommandRetryPolicy.ExecuteAction(
() => cnn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType)
);
}
}
}
发布后不久,我发现了一个名为 Polly that seems to solve this "retry" issue. I tracked it down via this Whosebug question 的包裹。
这是我从 MySQL 数据库查询并在失败时重试的实现:
var policy = Policy
.Handle<AuthenticationException>(ex => ex.InnerException is Win32Exception)
.Or<AuthenticationException>()
.Retry((exception, attempt) =>
{
Log.Error(exception, "Class: {Class} | Method: {Method} | Failure executing query, on attempt number: {Attempt}", GetType().Name,
MethodBase.GetCurrentMethod().Name, attempt);
});
try
{
var token = new Token();
policy.Execute(() =>
{
using (var connection = _mySqlDatabase.GetConnection())
{
token = connection.Query<Token>("SELECT * FROM Token...").FirstOrDefault();
}
});
return token;
}
catch (Exception ex)
{
Log.Error(ex, "Class: {Class} | Method: {Method} | Ultimately failed to retrieve data from the database", GetType().Name,
MethodBase.GetCurrentMethod().Name);
throw new HttpError(HttpStatusCode.InternalServerError);
}
是否有任何 ASP.NET package/DLL 允许 MySQL 查询执行失败时重试?
我已阅读有关 Transient Fault Handling and even came across a Dapper issue which shows an example 的内容,但根据我的研究,这仅适用于 SqlServer and/or Azure。
我的技术栈如下:
- .NET 4.5.2
- 小巧玲珑 1.50.2.0
- MySQL 5.6(使用 Amazon Aurora)
最终我正在尝试解决 sporadic failure issue 我相信实施一些重试逻辑将有助于缓解问题。
我尝试实现此 Dapper issue but because I am using MySql.Data 中的一些代码以连接到我的 MySql 数据库,它不适用于特定于 SqlServer 连接的各种方法。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Dapper;
using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
namespace TransientDapper
{
public static class TransientDapperExtensions
{
private static readonly RetryManager SqlRetryManager = GetDefaultRetryManager();
private static readonly RetryPolicy SqlCommandRetryPolicy = SqlRetryManager.GetDefaultSqlCommandRetryPolicy();
private static readonly RetryPolicy SqlConnectionRetryPolicy =
SqlRetryManager.GetDefaultSqlConnectionRetryPolicy();
private static RetryManager GetDefaultRetryManager()
{
const int retryCount = 4;
const int minBackoffDelayMilliseconds = 2000;
const int maxBackoffDelayMilliseconds = 8000;
const int deltaBackoffMilliseconds = 2000;
var exponentialBackoffStrategy =
new ExponentialBackoff(
"exponentialBackoffStrategy",
retryCount,
TimeSpan.FromMilliseconds(minBackoffDelayMilliseconds),
TimeSpan.FromMilliseconds(maxBackoffDelayMilliseconds),
TimeSpan.FromMilliseconds(deltaBackoffMilliseconds)
);
var manager = new RetryManager(
new List<RetryStrategy>
{
exponentialBackoffStrategy
},
exponentialBackoffStrategy.Name
);
return manager;
}
public static void OpenWithRetry(this SqlConnection cnn)
{
cnn.OpenWithRetry(SqlConnectionRetryPolicy);
}
public static IEnumerable<T> QueryWithRetry<T>(
this SqlConnection cnn, string sql, object param = null, IDbTransaction transaction = null,
bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
)
{
return SqlCommandRetryPolicy.ExecuteAction(
() => cnn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType)
);
}
}
}
发布后不久,我发现了一个名为 Polly that seems to solve this "retry" issue. I tracked it down via this Whosebug question 的包裹。
这是我从 MySQL 数据库查询并在失败时重试的实现:
var policy = Policy
.Handle<AuthenticationException>(ex => ex.InnerException is Win32Exception)
.Or<AuthenticationException>()
.Retry((exception, attempt) =>
{
Log.Error(exception, "Class: {Class} | Method: {Method} | Failure executing query, on attempt number: {Attempt}", GetType().Name,
MethodBase.GetCurrentMethod().Name, attempt);
});
try
{
var token = new Token();
policy.Execute(() =>
{
using (var connection = _mySqlDatabase.GetConnection())
{
token = connection.Query<Token>("SELECT * FROM Token...").FirstOrDefault();
}
});
return token;
}
catch (Exception ex)
{
Log.Error(ex, "Class: {Class} | Method: {Method} | Ultimately failed to retrieve data from the database", GetType().Name,
MethodBase.GetCurrentMethod().Name);
throw new HttpError(HttpStatusCode.InternalServerError);
}