Bug #69039 When using connection pooling .NET connector may occasionally return no data
Submitted: 23 Apr 2013 8:07 Modified: 9 Jan 2015 9:48
Reporter: Andrew Kostousov Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:6.6.5 OS:Windows
Assigned to: Roberto Ezequiel Garcia Ballesteros CPU Architecture:Any
Tags: connection pooling

[23 Apr 2013 8:07] Andrew Kostousov
Description:
From time to time in production we encounter the following problem. When querying a table by key MySql .Net connector returns empty record set when it definitely should return one record (if we repeat the same request we get correct answer).

We have a table 'Boxes' with primary key 'boxId' having ~500000 distinct records. This table changes very rarely and there are only inserts/updates to this table. Reads of this table are much more frequent. To read it we use a simple SELECT query: "SELECT * FROM Boxes WHERE boxId = @boxId".

Presumably in the face of network errors MySql connector occasionally returns empty record set for that query for existing boxId keys (in logs we see timeouts  prior to faulty requests).

Our production environment is as follows:
* MySql Server v5.1 running on CentOS release 6.4 (Final) Linux 2.6.32-358.2.1.el6.x86_64
* .Net4 console app running on Windows Server 2008 R2 SP1 x64
* MySql .Net Connector v6.6.5
* Connection string is like this: Server=<host-name>;Database=<db-name>;Uid=<user-name>;Pwd=<password>

How to repeat:
To reproduce described behavior we set up the following testing environment:
* MySql Server v5.1 running on CentOS release 6.3
* Testing console .Net4 app running on Windows 7 SP1 x64
* MySql .Net connector (MySql.Data.dll, Version=6.6.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d) downloaded from here: http://dev.mysql.com/downloads/connector/net/#downloads
* Connection string: Server=xxx;Database=yyy;Uid=xx;Pwd=yy;Connection Timeout=1;Pooling=true;Max Pool Size=100;Min Pool Size=0;ConnectionReset=false;ConnectionLifeTime=0;

We created table 'Boxes' with the following script:

CREATE TABLE `Boxes` (
  `boxId` char(36) NOT NULL,
  `orgId` char(36) NOT NULL,
  PRIMARY KEY (`boxId`)
)

And filled it with ~10000 records using random GUIDs.

Then to simulate bad network we set up the following iptables rules on the server:
* -A INPUT -m state --state NEW -m tcp -p tcp -s 192.168.13.181 --dport 3306 -j ACCEPT
* -A INPUT -m tcp -p tcp -s 192.168.13.181 --dport 3306 -m statistic --mode random --probability 0.15 -j DROP
* -A OUTPUT -m tcp -p tcp -d 192.168.13.181 --sport 3306 -m statistic --mode random --probability 0.15 -j DROP

where 192.168.13.181 is the IP-address of the client.

With the following code in the client app we were able to consistently reproduce the bug:

private void Run()
{
  var allBoxes = GetAllBoxes();
  while (true)
  {
    foreach (var boxId in allBoxes)
    {
      try
      {
        var box = PerformReadonlyRequest(boxId);
        if (box != null)
          log.InfoFormat("OK! box was found for boxId: {0}", boxId); //<-- getting here when request succeedes
        else
          log.ErrorFormat("BUG!!! box not found for boxId: {0}", boxId); //<-- this should never happen
      }
      catch (Exception e)
      {
        log.Error(string.Format("Error connecting to mysql"), e); //<-- getting here on connection errors
      }
    }
  }
}

private static Box PerformReadonlyRequest(Guid boxId)
{
  Box box = null;
  var sql = "SELECT * FROM Boxes WHERE boxId = '" + boxId + "'";
  using (var rdr = MySqlHelper.ExecuteReader(connectionString, sql))
  {
    if (rdr.Read())
    {
      box = new Box
      {
        BoxId = (Guid)rdr["boxId"],
        OrgId = (Guid)rdr["orgId"],
      };
    }
  }
  return box;
}

allBoxes variable is filled with a fixed list of all different keys from table 'Boxes'.

Instead of getting exceptions for bad requests we are observing "BUG!!!" records in the log file in a couple of minutes after the client starts.

When we change connection string to "Server=xxx;Database=yyy;Uid=xx;Pwd=yy;Connection Timeout=1;Pooling=false;" everything works as expected.

We've tried several versions of .Net-connector and found out that bug reproduces with v6.7.1 (latest dev version) and does not show up when using v6.0.7.
[28 Jun 2013 2:22] Philip Olson
Fixed as of the upcoming Connector/Net 6.5.7, 6.6.6, and 6.7.4 releases, and here's the changelog entry:

Sometimes no data was returned when a socket connection was slow,
interrupted, or delayed. The timeout is now properly reported as an error
to the upper layers.

Thank you for the bug report.
[20 Sep 2013 10:03] Andrew Kostousov
I'm still able to reproduce this bug with 6.6.6 and 6.7.4 versions of mysql.data.dll :-(
[22 Sep 2015 14:02] Justin Wyer
This is (still?) occurring with 6.9.7.