Bug #24373 High CPU utilization when no idle connection
| Submitted: | 16 Nov 2006 21:35 | Modified: | 27 Feb 2007 11:19 |
|---|---|---|---|
| Reporter: | Karl Seguin | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / NET | Severity: | S5 (Performance) |
| Version: | 5.0.x | OS: | Windows (Win32) |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | .net, pooling, timeout | ||
[16 Nov 2006 21:45]
Karl Seguin
Sorry, the last point about "CreateNewPooledConnection" was just an unrelated remark...
[22 Nov 2006 12:21]
Tonci Grgin
Karl, thanks for your excellent problem report. Verified as described by reporter with latest sources. Until timeout expires, CPU is locked at 100%: Connecting to Mysql DB error connecting: Timeout expired. The timeout period elapsed prior to obtainin g a connection from the pool. This may have occurred because all pooled connect ions were in use and max pool size was reached.
[22 Nov 2006 12:22]
Tonci Grgin
Test case
Attachment: Program.cs (text/plain), 1.50 KiB.
[22 Feb 2007 20:06]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/20413
[22 Feb 2007 20:07]
Reggie Burnett
Fixed in 1.0.10 and 5.0.4
[22 Feb 2007 20:52]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/20420
[27 Feb 2007 11:19]
MC Brown
A note has been added to the 5.0.4 and 1.0.10 changelogs.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.041 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: MySqlPool.GetConnection runs a very tight loop until there's either a timeout or a connection is retrieved from the pool. Specifically: while (driver == null && (Environment.TickCount - startTime) < timeOut) { driver = GetPooledConnection(); } private Driver GetPooledConnection() { while (idlePool.Count <= 0) { if (inUsePool.Count == maxSize) { return null; } CreateNewPooledConnection(); } return CheckoutConnection(); } If there are no idle connections in idlePool and we are using the maximum amount of connections, we'll just spin our wheels in the loop. This can have a pretty harsh performance impact on a system which is pushing up against it's connection limit. How to repeat: This code will reproduce the problem each time. Using a profiler, perfmon or just task-manager, we can see the impact on performance this code will have. I used snippet compiler, so WL and RL just map to Console.WriteLine and Console.ReadLine . private const string _connectionString = "XXXXXX;Maximum Pool Size=1"; public static void Main() { MySqlConnection connection1 = null; MySqlConnection connection2 = null; try { connection1 = GetConnection(); connection2 = GetConnection(); } catch(Exception ex) { WL(ex); } finally { if (connection1 != null) { connection1.Dispose(); } if (connection2 != null) { connection2.Dispose(); } } WL("Done"); RL(); } private static MySqlConnection GetConnection() { MySqlConnection connection = new MySqlConnection(_connectionString); connection.Open(); return connection; } Suggested fix: I don't know what people think about sleeping inside the while loop... Ideally it'd be nice to see this block and wait for a signal that a connection has become available. From a performance standpoint, it'd be nice if CreateNewPooledConnection() actually Checkedout and returned the connection directly. As is, 1 thread can keep creating new pool connections while other threads sneak in and steal them.