Bug #96636 MySqlConnection.Open() slow under load when using SSL
Submitted: 23 Aug 2019 10:58 Modified: 10 Sep 2019 7:16
Reporter: Lee Sanderson Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / NET Severity:S5 (Performance)
Version:6.10.9 OS:Any
Assigned to: CPU Architecture:Any

[23 Aug 2019 10:58] Lee Sanderson
Description:
The MySqlConnection.Open() can take 30+ seconds when using SSL to connect to a MySql server if multiple threads are trying to connect at the same time.

The root of the problem seems to be with the Ssl.StartSSL method - which creates a lock while executing sslStream.AuthenticateAsClientAsync (and thus blocks any other connections when waiting for a response).

How to repeat:
The following code reliably replicates the problem:

    class Program
    {
        static void Main()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["test"].ConnectionString;
            var builder = new MySqlConnectionStringBuilder(connectionString);

            builder.SslMode = MySqlSslMode.Required;
            builder.Pooling = true;
            builder.MaximumPoolSize = 1000;
            builder.MinimumPoolSize = 0;
            builder.ConnectionLifeTime = 1;

            int connectsExecuted = 0;
            int slowConnects = 0;
            long slowestConnectionTime = 0;
            Parallel.For(
                0, 10000, (i) =>
                {
                    var connection = new MySqlConnection(builder.ConnectionString);
                    var connectionId = Interlocked.Increment(ref connectsExecuted);
                    var sw = Stopwatch.StartNew();
                    connection.Open();
                    var elapse = sw.ElapsedMilliseconds;
                    if (elapse > 2000)
                    {
                        Debugger.Break();
                        Interlocked.Increment(ref slowConnects);
                        if (elapse > slowestConnectionTime)
                        {
                            slowestConnectionTime = elapse;
                        }
                    }

                    Thread.Sleep(10); // Simulate usage of conection 
                    connection.Close();
                });

            Console.WriteLine($"{slowConnects} of {connectsExecuted} connections slow - slowest conection = {slowestConnectionTime} ms");
        }
    }

The slowest connection times vary but typically can be 2-30 seconds. We have reports of 40+ seconds on production systems

Suggested fix:
Alter Ssl.StartSSL so that locks are not taken during the authentication process.
[10 Sep 2019 7:16] MySQL Verification Team
Hello Lee Sanderson,

Thank you for the report and feedback.

regards,
Umesh