/// <summary>
/// 若使用【读写分离】,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
/// </summary>
/// <param name="readerHander"></param>
/// <param name="cmdType"></param>
/// <param name="cmdText"></param>
/// <param name="cmdParms"></param>
public void ExecuteReader(Action <MySqlDataReader> readerHander, CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms)
{
DateTime dt = DateTime.Now;
string logtxt = "";
DateTime logtxt_dt = DateTime.Now;
var pool = this.MasterPool;
bool isSlave = false;
//读写分离规则
if (this.SlavePools.Any() && cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase))
{
var availables = slaveUnavailables == 0 ?
//查从库
this.SlavePools : (
//查主库
slaveUnavailables == this.SlavePools.Count ? new List <MySqlConnectionPool>() :
//查从库可用
this.SlavePools.Where(sp => sp.IsAvailable).ToList());
if (availables.Any())
{
isSlave = true;
pool = availables.Count == 1 ? availables[0] : availables[slaveRandom.Next(availables.Count)];
}
}
Object <MySqlConnection> conn = null;
var pc = PrepareCommand(cmdType, cmdText, cmdParms, ref logtxt);
if (IsTracePerformance)
{
logtxt += $"PrepareCommand: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
}
Exception ex = null;
try {
if (IsTracePerformance)
{
logtxt_dt = DateTime.Now;
}
if (isSlave)
{
//从库查询切换,恢复
bool isSlaveFail = false;
try {
if (pc.cmd.Connection == null)
{
pc.cmd.Connection = (conn = pool.Get()).Value;
}
//if (slaveRandom.Next(100) % 2 == 0) throw new Exception("测试从库抛出异常");
} catch {
isSlaveFail = true;
}
if (isSlaveFail)
{
if (conn != null)
{
if (IsTracePerformance)
{
logtxt_dt = DateTime.Now;
}
pool.Return(conn, ex);
if (IsTracePerformance)
{
logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
}
LoggerException(pool, pc.cmd, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
pc.cmd.Parameters.Clear();
ExecuteReader(readerHander, cmdType, cmdText, cmdParms);
return;
}
}
else
{
//主库查询
if (pc.cmd.Connection == null)
{
pc.cmd.Connection = (conn = pool.Get()).Value;
}
}
if (IsTracePerformance)
{
logtxt += $"Open: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
logtxt_dt = DateTime.Now;
}
using (MySqlDataReader dr = pc.cmd.ExecuteReader()) {
if (IsTracePerformance)
{
logtxt += $"ExecuteReader: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
}
while (true)
{
if (IsTracePerformance)
{
logtxt_dt = DateTime.Now;
}
bool isread = dr.Read();
if (IsTracePerformance)
{
logtxt += $" dr.Read: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
}
if (isread == false)
{
break;
}
if (readerHander != null)
{
object[] values = null;
if (IsTracePerformance)
{
logtxt_dt = DateTime.Now;
values = new object[dr.FieldCount];
dr.GetValues(values);
logtxt += $" dr.GetValues: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
logtxt_dt = DateTime.Now;
}
readerHander(dr);
if (IsTracePerformance)
{
logtxt += $" readerHander: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms ({string.Join(",", values)})\r\n";
}
}
}
if (IsTracePerformance)
{
logtxt_dt = DateTime.Now;
}
dr.Close();
}
if (IsTracePerformance)
{
logtxt += $"ExecuteReader_dispose: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
}
} catch (Exception ex2) {
ex = ex2;
}
if (conn != null)
{
if (IsTracePerformance)
{
logtxt_dt = DateTime.Now;
}
pool.Return(conn, ex);
if (IsTracePerformance)
{
logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
}
}
LoggerException(pool, pc.cmd, ex, dt, logtxt);
pc.cmd.Parameters.Clear();
}