Is there a programmatic way to find the current number of open connections to the database that are being maintained by the .Net connector/MySql.Data.dll?
I'm interested in collecting this information within the same program as the library is used.
接続プーリングはクライアント側で実行されます。これにアクセスするには、リフレクションを使用して MySql.Data アセンブリの内部にある MySqlPoolManager および MySqlPool クラスにアクセスする必要があります。
基本的に、リフレクションを使用してプールにアクセスする必要があります。方法は次のとおりです。
Assembly ms = Assembly.LoadFrom("MySql.Data.dll");
Type type = ms.GetType("MySql.Data.MySqlClient.MySqlPoolManager");
MethodInfo mi = type.GetMethod("GetPool", BindingFlags.Static | BindingFlags.Public);
var pool = mi.Invoke(null, new object[] { new MySqlConnectionStringBuilder(connString) });
MySqlConnectionStringBuilder
オブジェクトを渡す必要があることに気付くでしょう。接続文字列ごとに個別のプールが作成されるため、アプリで使用するのと同じ接続文字列を使用します (完全に同一である必要があります)。
その後、必要な情報を取得するために、(ここでもリフレクションを使用して) プライベート プールのフィールドとプロパティにアクセスできます。特に、"available" フィールドと "NumConnections" プロパティは、おそらく関心のあるものでしょう。「idlePool」(a Queue<>
) と「inUsePool」(a List<>
) もあり、特にカウントにアクセスできます。
この質問に対するピートの回答とこの他の回答のおかげで、以下の関数を構築できました。
/// <returns>totalAvailable, inUseCount, idleCount</returns>
public int[] GetPoolStatsViaReflection(MySqlConnectionStringBuilder connectionStringBuilder)
{
var asm = typeof(MySqlConnectionStringBuilder).Assembly;
var poolManagerType = asm.GetType("MySql.Data.MySqlClient.MySqlPoolManager"); // internal sealed
var poolType = asm.GetType("MySql.Data.MySqlClient.MySqlPool"); // internal sealed
var pool = poolManagerType.InvokeMember("GetPool", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, null, new object[] { connectionStringBuilder });
const System.Reflection.BindingFlags nonPublicInstanceField = System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
var totalAvailable = (int)poolType.InvokeMember("available", nonPublicInstanceField, null, pool, new object[] { });
// List<Driver>
var inUsePool = (System.Collections.ICollection)poolType.InvokeMember("inUsePool", nonPublicInstanceField, null, pool, new object[] { });
// Queue<Driver>
var idlePool = (System.Collections.ICollection)poolType.InvokeMember("idlePool", nonPublicInstanceField, null, pool, new object[] { });
return new[] {totalAvailable, inUsePool.Count, idlePool.Count};
}