| Bug #40036 | Connector "lost" pooled connections. | ||
|---|---|---|---|
| Submitted: | 15 Oct 2008 8:25 | Modified: | 24 Sep 21:12 |
| Reporter: | Moshe Lampert | ||
| Status: | Verified | ||
| Category: | Connector/Net | Severity: | S2 (Serious) |
| Version: | 6.0.3 | OS: | Any |
| Assigned to: | Reggie Burnett | Target Version: | |
| Tags: | pooling, NET | ||
| Triage: | D2 (Serious) | ||
[15 Oct 2008 8:25]
Moshe Lampert
[15 Oct 2008 8:30]
Moshe Lampert
(fix a mistake)
[21 Oct 2008 17:53]
Tonci Grgin
Hello Moshe and thanks for your report. I am puzzled as to what do you expect from me now? To build-up "heavy" web site and test? If not then there must be a test case but I don't see it attached. However, I feel this needs some investigation but don't know where to start...
[21 Oct 2008 19:28]
Moshe Lampert
My testcase is super-simple.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
Dim Conn As New MySqlConnection("server=localhost;user id=root; password=...;
database=...; pooling=true;")
Conn.Open()
[21 Oct 2008 19:30]
Moshe Lampert
(sorry, 'enter' pressed)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
Dim Conn As New MySqlConnection("server=localhost;user id=root; password=...;
database=...; pooling=true;")
Conn.Open()
Dim Cmd As New MySqlCommand("select * from homepage", Conn)
Dim oReader As MySqlDataReader = Cmd.ExecuteReader()
While oReader.Read
' do something / do nothing
End While
oReader.Close()
Cmd.Dispose()
Conn.Close()
Conn.Dispose()
End Sub
[21 Oct 2008 19:30]
Moshe Lampert
(sorry, 'enter' pressed)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
Dim Conn As New MySqlConnection("server=localhost;user id=root; password=...;
database=...; pooling=true;")
Conn.Open()
Dim Cmd As New MySqlCommand("select * from homepage", Conn)
Dim oReader As MySqlDataReader = Cmd.ExecuteReader()
While oReader.Read
' do something / do nothing
End While
oReader.Close()
Cmd.Dispose()
Conn.Close()
Conn.Dispose()
End Sub
[21 Oct 2008 19:30]
Moshe Lampert
(sorry, 'enter' pressed)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
Dim Conn As New MySqlConnection("server=localhost;user id=root; password=...;
database=...; pooling=true;")
Conn.Open()
Dim Cmd As New MySqlCommand("select * from homepage", Conn)
Dim oReader As MySqlDataReader = Cmd.ExecuteReader()
While oReader.Read
' do something / do nothing
End While
oReader.Close()
Cmd.Dispose()
Conn.Close()
Conn.Dispose()
End Sub
[21 Oct 2008 19:34]
Moshe Lampert
sleeped connections
Attachment: Untitled.gif (image/gif, text), 21.71 KiB.
[21 Oct 2008 19:35]
Moshe Lampert
(Sorry, 'enter' pressed - my keyboard need to replaced!)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
Dim Conn As New MySqlConnection("server=localhost;user id=root; password=...;
database=...; pooling=true;")
Conn.Open()
Dim Cmd As New MySqlCommand("select * from homepage", Conn)
Dim oReader As MySqlDataReader = Cmd.ExecuteReader()
While oReader.Read
' do something / do nothing
End While
oReader.Close()
Cmd.Dispose()
Conn.Close()
Conn.Dispose()
End Sub
I'm used Microsoft's Web Applications Stress Tool to make a 100 requests/sec and after a
while I get this:
[12 Nov 2008 18:33]
Moshe Lampert
after a some weeks of testing (Windows 2003 - IIS6, Windows Vista - IIS7), my conclusion is that connection get re-used 20-30 times (with 1-2 secs) and after a while "losted". when I set "Connection Lifetime" to 1 sec, I see much less losted connections. show full processlist (lifetime=10) result: 1040, 'a7', 'localhost:57158', 'a7new', 'Sleep', 226, '', '' 1041, 'a7', 'localhost:57164', 'a7new', 'Sleep', 203, '', '' 1042, 'a7', 'localhost:57177', 'a7new', 'Sleep', 183, '', '' 1044, 'a7', 'localhost:57188', 'a7new', 'Sleep', 126, '', '' 1045, 'a7', 'localhost:57220', 'a7new', 'Sleep', 103, '', '' 1046, 'a7', 'localhost:57222', 'a7new', 'Sleep', 83, '', '' 1048, 'a7', 'localhost:57248', 'a7new', 'Sleep', 26, '', '' 1049, 'a7', 'localhost:57258', 'a7new', 'Sleep', 3, '', '' 1050, 'a7', 'localhost:57259', 'a7new', 'Sleep', 3, '', '' 1051, 'root', 'localhost:57260', 'a7new', 'Query', 0, '', 'show full processlist'
[18 Feb 11:34]
Tonci Grgin
Moshe, I think the problem is in IIS pooling. Can you please try and shut it down (again, not c/NET but IIS pooling) and retest as IIS is partly responsible for pooling mechanisms and I want to check if it does not release connections from pool properly. Again, probably stale connections are not released from pool by IIS and/or you are not checking them before reuse and/or pool can not accommodate such high traffic and/or MySQL server is configured so that it can't give you requested number of connections (you should be able to find out which scenario is in effect with netstat and "show processlist") .
[18 Feb 12:04]
Bogdan Degtyariov
Moshe, If your web server is heavily loaded you should consider increasing the "max pool size" connection string parameter, which is 100 by default. For the environments with medium and low database activity the default value is ok, but in your case the pool can exhaust too quickly. Thanks.
[18 Feb 13:11]
Moshe Lampert
IIS pooling/webgarden disabled. Max pool size is not the problem in this server (without pooling, show full processlist shows 10-12). I think the problem is in the connector itself, while connections still opened when "Connection Lifetime" is reached, and the max pool (any pool, 300 for example) will be reached. (I checked 5.2.4, 5.2.5 - same problem)
[14 Mar 7:28]
Antonio García
I have a WindowsForms application running using connector for .NET, just sitting MySQL
next to my app on the same machine, and I have the very same problem that Moshe
explains.
You can use the code he provided in his last post, and it will fail on winforms
application too.
I also made a debug on the sources and I could see that the error is because when a new
connection is requested this test fails:
if (!HasIdleConnections) <--- This condition FAILS
driver = CreateNewPooledConnection(); <--- So it creates a new connection
else
driver = CheckoutConnection(); <--- Instead of reusing an existing one
(located in GetPooledConnection function on MySQLPool.cs, line 150)
and it fails because idlePool is empty, but MySQL Administrator shows THERE ARE idle
connections, so due to that fact, connector makes the decision to create a new connection
and therefore the idle connection is wasted and never recovered because the reference to
the connection has been lost.
I couldn't figure out the condition that makes idlePool to be empty when there still are
connections available (understanding all of connector code was out of scope to me)
The error is present in connector 6 too. I tried both versions and fails the same way.
[14 Mar 7:30]
Antonio García
Screenshot showing the error described
Attachment: ScreenShot.JPG (image/jpeg, text), 131.89 KiB.
[14 Mar 22:07]
Tonci Grgin
Antonio, "SLEEP" word has mislead you. Connection to MySQL server that is in "SLEEP" state actually *waits* for something from server. So please do not mix c/NET or IIS pooled connection state with MySQL server connection state. As I am not convinced there is no bug here, it's still in analyzing.
[15 Mar 0:33]
Antonio García
Let's say I'm wrong, due to the fact connections are sleeping and waiting for something to happen instead of IDLE. But anyway, connection pooling means reusing connections, the connections shown are connections that were used, then they were closed/disposed and are supposed to go back to the pool. Well that's something that doesn't happen. If I continue executing the application, a lot more "sleeping" connections appear until I reach max pool size and then MySQL refuses further connections with error "Too many connections" Ok, they are not idle, they're sleeping, but why?? I closed/disposed every connection (I need to use many connections since connector doesn't support MARS) so why they sleep instead of getting idle? Why connection pool doesn't reuse them? You say they are waiting for something in server, please tell me what can possibly be waiting a connection that was closed? Why connection pooling are not reusing them? As you can see, maybe the names of the connection states are not correct, but I think THERE is a bug, since connection pool is NOT reusing them. The connection String I'm using is this, hope it helps "Database=omnivent;Port=3306;Pooling=True;Use Compression=True;Server=localhost;User Id=XXXXX;Password=YYYYY;Allow Batch=True;Connect Timeout=10" Thanks in advance
[20 Mar 0:26]
Milan Burmaja
I just want to confirm same problem with WinForms and 5.2.5 connector. Until few weeks ago I've used 5.0.6 and there was no problem Milan
[23 Mar 5:13]
Antonio García
Tonci: Any news on this?
[26 Mar 17:04]
Nicklas Holmgren
Hi I also have the same problem... I use Subsonic 2.1 with mysql 5.2.5. (maybe I can upgrade to mysql 6.0 and it'll magically go away?) I had same problem with 5.2.3 just so u know. [MySqlException (0x80004005): error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.] MySql.Data.MySqlClient.MySqlPool.GetConnection() +184 MySql.Data.MySqlClient.MySqlConnection.Open() +335 SubSonic.MySqlDataProvider.CreateConnection(String newConnectionString) +61 SubSonic.MySqlDataProvider.CreateConnection() +46
[26 Mar 17:09]
Tonci Grgin
Guys, this is very stretched but try this: o Increase connection timeout o Change the registry parameter responsible for the number of TCP ports on Windows as described in http://dev.mysql.com/doc/refman/5.0/en/can-not-connect-to-server.html#can-not-connect-to-s... o Retest Remember that for each different connection string you get separate pool.
[26 Mar 17:11]
Tonci Grgin
too fast... o Check max_connections on server and adjust all pool sizes accordingly
[26 Mar 21:07]
Tonci Grgin
Guys, we are working vigorously but with no progress... All we've gathered so far are bits and pieces. So here's another one: http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx Do you errors appear when you're close to or over the MaxWorkerThreads? If so, it's limitation of framework and OS. This might also be the answer to Antonio's questions "sleeping but why?".
[26 Mar 22:03]
Antonio García
Tonci:
I already tried your suggestions, but with no success =(
Increasing pool size just delays the error but it happens anyway.
In the other hand, I don't really think that worker threads has something to do, at least
in my particular case, due to the fact that connections go to sleep immediatly after
connection is closed/disposed. And even if I don't reach the connection limit (e.g. I
quit from the application), I have a lot of sleeping connections that never get reused,
but interesting thing is when application is closed all the connections are freed
correctly (because they are in the "InUse" or" ActivePool" -don't remember variable name-
collection, I noticed that when debugged the code). Nothing is left behind.
I do use worker threads, they are in the worst case 3 worker threads concurrently
working, but the problem reported is easily reproduced even with just the main thread of
the application.
Error regarding connection limit ("Too many connections") is only thrown when I reach the
max pool size (I also tried with a hardcoded version of connection string just to avoid
getting different pools. The problem is just the same)
I hope this info help you to detect the problem.
Thanks
[27 Mar 13:56]
Nicklas Holmgren
I'm looking forward to hear more in the matter. Do you think things will be solved if I switch over to mysql 6.0 on server and connector?
[27 Mar 17:33]
Tonci Grgin
There's been new update on this. Support is currently testing workaround for possible cause of this problem. More to the point, we are to moving Ping() requests out of the locked section. Workflow: Now: (1) lock the pool object (2) get pooled connection or create a new one if pool is empty (3) ping the server using the connection from step 2 (4) mark connection as valid if ping finished successfully or create a new connection (5) unlock the pool object Consequently, all requests to the pool have to wait until ping() finishes and the pool is unlocked. Testing: (1) lock the pool object (2) get pooled connection or create a new one if pool is empty (3) unlock the pool object (4) ping the server using the connection from step 2 (5) mark connection as valid if ping finished successfully or create a new connection We have high hopes this will cure the problem you're seeing or, at least, improve status a bit. After testing, Reggie will make the final call.
[1 Apr 17:04]
Nicklas Holmgren
Currently I've set pooling=false which solves it for me, but I'm guessing at a pretty high loss of speed. I am waiting for this solution eagerly :) How's the testing going?
[2 Apr 11:54]
Nicklas Holmgren
The change to pooling=false hasn't solved the issue for me! I'm still getting occurencies of unable to connect to any of the specified mysql hosts. when clearly the mysql host is up and alive. what suggestions do you have for me?
[2 Apr 12:07]
Tonci Grgin
Nicklas, there have been situations in which new code could produce deadlock so we're refining it. As for you concrete case, I am really not a magician... Probably you're hitting some framework or server limitation, don't know...
[8 Apr 16:03]
Nicklas Holmgren
I did the adjustments you told about [26 Mar 17:09] and site has been running stable since.. also did some optimizations where I saw I opened so many unecessary connections. I made stored procs of them and joined the results and gained much nicer performance and much much less connections opened... thx. obviously we hit the limit of 5000 connections at once, probably due to sloppy coding
[8 Apr 16:22]
Tonci Grgin
Nicklas, glad things function now... This is just to show how complex connectors matter are. You never know where the devil is. Especially on windows.
[8 Apr 18:24]
Antonio García
Hi Toncy, Is there any news on the correction you told us about (March 27th)?
[9 Apr 8:20]
Tonci Grgin
Antonio, unfortunately no news for now. Each patch goes through rigorous testing process even though it appears to be correct or functioning...
[9 Apr 17:57]
Tonci Grgin
Probably same problem as described in Bug#43349.
[21 Apr 2:35]
José García
Hi. I am just migarting an appication I have with .Net C# from SQL Express to MySQL 6.0. Same problem with connections and timeing out. Do you have any news on this issue?
[21 Apr 2:39]
José García
By the way, solution from March 26th didn't work for me either; however pooling=false worked, but very slow; end user is gona kill me if I release my system with this "solution" I would appreciate if you have any news on this.
[18 May 20:39]
Moshe Lampert
After a deep searching inside code, on our test and production servers, I found solution for a 50%~ of the connections losted. If pooling is disabled and something fail: open > work > error > GC closed connection If pooling is open, pooler has a some type of array of in-use connections, when some code fail, GC found refrence to opened connection in the array and keeps the connection object, and the object will marked "in-use" forever. I solve it (not 100% ! the problem is inside from other reasons) with using "With": Using Conn As New MySqlConnection(ConnString) Conn.Open() End Using in ASP.NET page (or base-class), option two: Private Sub Page_Error(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Error Conn.Close() : Conn.Dispose() End Sub this is not a perefect solution, but reduced losted connections.
[20 Jun 10:51]
Tonci Grgin
Bug#43349 is marked as duplicate of this report.
[20 Jul 0:15]
d di
Hi guys I'd like to know if this problem can be reproduced with an alternative pooling algorithm, if you have time try out http://bugs.mysql.com/file.php?id=12463 (from issue #40684) and see if that helps or makes things worse.
[24 Sep 13:29]
Moshe Lampert
something new? The connector may need to check if connection losted open, then return to the pool, or set a "timeout" for connection, and return automatically to the pool to solve this problem.
[24 Sep 21:12]
Tonci Grgin
Moshe, not that I know of. Will look into status when I return from vacation. I also made mistake by leaving report in Analyzing instead of Verified...
[28 Sep 10:59]
Dan orsborne
I had the same issue with the connector. Turns out there is an issue with pooling that exists in all versions from 5.1.7 up to current version (It's still not fixed). Download the complete source and apply the changes in this post and it works perfectly! http://bugs.mysql.com/bug.php?id=31996
