Description:
If the database that an application using the Connector/NET library is trying to connect to is down, the first connection attempt will fail, as expected, and the MySqlConnection.Open() method will throw an exception.
If the application retries the connection attempt a second time, the MySqlConnection.Open() method will hang, never returning or throwing an exception.
This only happens if the connection is using pooling, and if MinimumPoolSize is greater than 0. Disabling pooling or setting MinimumPoolSize to 0 results in expected behavior, where each connection attempt throws an exception, as expected.
This is reproducible starting in version 8.2.0, and continues to be reproducible with 8.3.0. It is not reproducible with 8.1.0.
This was tested against MySQL Server 8.0.36, but the server version should not matter, since the problem occurs when the server is not running.
How to repeat:
Establish a connection to a MySQL database using Connector/NET via a connection string that sets MinimumPoolSize to a value greater than 0. Verify that the connection attempt is successful.
Shut down the MySQL database and try the connection attempt again. Verify that the attempt fails and throws an exception with an appropriate error message.
Have the application retry the failed connection attempt a second time. Note that the second connection attempt never returns and never throws an exception.
Example code:
internal class Program
{
static void Main(string[] args)
{
var builder = new MySqlConnectionStringBuilder
{
Server = "localhost",
Database = "test",
UserID = "test",
Password = "test",
MinimumPoolSize = 1,
};
var counter = 1;
while (true)
{
Console.WriteLine($"Connection attempt {counter++}");
try
{
using (var conn = MySqlClientFactory.Instance.CreateConnection())
{
conn.ConnectionString = builder.GetConnectionString(includePass: true);
conn.Open();
Console.WriteLine("Connection established ok");
return;
}
}
catch (Exception ex)
{
Console.WriteLine("Error establishing connection: " + ex.Message);
Console.WriteLine("Waiting 5 seconds before retry...");
Thread.Sleep(5000);
}
}
}
}