Possible Memory Leak in MySQL connection

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for MySQL
Post Reply
vincentfitzg
Posts: 10
Joined: Wed 27 Jul 2005 11:36

Possible Memory Leak in MySQL connection

Post by vincentfitzg » Fri 25 Jan 2008 11:57

Hi,
We have memory problems in a multithreaded application. We create a number of threads to read a number of large blobs (4-20MB each) from the database. The memory rises sharply at the beginning but never goes down to the orignal level.
A memory profiler shows that the memory is in a byte array in the MySQlInternalConnection. Even after closing and disposing the connection the memory remains the same. It looks as if the connection is keeping a reference to the data that was read out last.

We are using version 3.5, I have downloaded the latest trial version 4.30 as well and get the same results. Developing using Visual Studio 2005 .

I have attached code below, I can also send a test database when required.

can you let me know if there is something wrog

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CoreLab.MySql;
using System.Threading;
using System.Collections;
using System.Diagnostics;
namespace WindowsApplication4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

static MySqlConnection GetConnection()
{
string connectionString;
connectionString = "server = localhost;";
connectionString += "database = Test DB;";
connectionString += "user id = root;";
connectionString += "pwd=;";

MySqlConnection connection = null;

try
{
connection = new MySqlConnection( connectionString );
}
catch
{
connection.Dispose();
connection = null;
return null;
}

try
{
connection.Open();
}
catch
{
if( connection != null )
{
connection.Dispose();
connection = null;
}
return null;
}
return connection;
}
private long GetMemory()
{
long page = Process.GetCurrentProcess().PagedMemorySize64 / 1024;
long ram = Process.GetCurrentProcess().WorkingSet64 / 1024;

long total = page + ram;

return total;
}
private void button1_Click( object sender, EventArgs e )
{

ArrayList threads = new ArrayList();
Thread thread;

long startmem = GetMemory();

for( int i = 0; i 0 )
{
using( MySqlBlob mySqlBlob = reader.GetMySqlBlob( 0 ) )
{
if( mySqlBlob != null && mySqlBlob.Value != null )
mySqlBlob.Dispose();
}
}
}
}
catch( Exception ex )
{
Console.WriteLine("Error:" + ex.Message);
}
}
connection.Close();
connection.Dispose();
connection = null;
GC.Collect();
}
}
}

Alexey.mdr
Posts: 729
Joined: Thu 13 Dec 2007 10:24

Post by Alexey.mdr » Fri 25 Jan 2008 12:26

Actual connection is not closed in order to be used later by your application. This is Connection Pooling feature in many cases this boosts performance greatly.
You can clear the pool explicitly. Generally pool is cleared automatically when connections are idle or closed by server. To force the operation call ClearPool or ClearAllPools methods. Another solution is to disable the pool at all (set Pooling=false in connection string). Please let us know, if this doesn't help.

vincentfitzg
Posts: 10
Joined: Wed 27 Jul 2005 11:36

Post by vincentfitzg » Fri 25 Jan 2008 14:31

Hi Alexey,
Thanks for the quick reply. I figured that it might have something to do with the connection pooling. I tried the ClearAllPools method and it does improve the memory situation but I would still like to use the connection pool, since it does increase the performance. And speed is very important for our application.

I understand that there is a list of previous connections stored for the pool to be used later, but what I dont understand is why they have a reference to so much data. If i create five threads and therefore five connections it will lose up to 50MB in memory. This cant just be memory to store pooled connections?
If i use the same code and return an index instead of the blob, then little or no memory is lost.

Thanks for your help

Alexey.mdr
Posts: 729
Joined: Thu 13 Dec 2007 10:24

Post by Alexey.mdr » Fri 25 Jan 2008 16:18

A special buffer allocates space in managed heap when you open a connection. The size of the buffer depends on the amount of bytes being transmitted. Hence if you open a connection and send BLOB files, the size of the buffer is going to be quite big. Then you close this connection, and despite of being garbage-collected, it moves to Connection Pool.
Next time you want to open a connection, it is going to be fetched from the pool. The system will not allocate memory again.
What you need to do is to play around with connection pooling to find a balance between speed and size.

Post Reply