I have a pool of MySQL connections for a web-based data service. When it starts to service a request, it takes a connection from the pool to use. The problem is that if there has been a significant pause since that particular connection has been used, the server may have timed it out and closed its end. I’d like to be able to detect this in the pool management code.
The trick is this: The environment in which I’m coding gives me only a very abstract API into the connection. I can basically only execute SQL statements. I don’t have access to the actual socket or direct access to the MySQL client API.
So, the question is: What is the cheapest MySQL statement I can execute on the connection to determine if it is working. For example SELECT 1; should work, but I’m wondering if there is something even cheaper? Perhaps something that doesn’t even go across the wire, but is handled in the MySQL client lib and effectively answers the same question?
Clarification: I’m not concerned about checking if the MySQL server is running, or if it’s database configuration is up enough to answer queries. If those things are down, then the subsequent SQL the service executes will get and handle the appropriate error. I’m only really concerned with if the TCP connection is open… since if the server closed it, then the web service’s SQL will get an error that means "just reconnect and try again", and that would be inconvenient to do once down in the muck of the service code.
You will not know the real state of the connection without going over the wire, and
SELECT 1is a good enough candidate (arguably you could come up with a shorter command which takes less time to parse, but compared to network or even loopback latency those savings would be insignificant.)This being said, I would argue that pinging a connection before checking it out from the pool is not the best approach.
You should probably simply have your connection pool manager enforce its own keep-alive (timeout) policy to avoid being disconnected by the server (short of a more serious intervening connectivity issue, which could affect you smack in the middle of regular operations anyway — and which your connection pool manager would be unable to help with anyway), as well as in order not to hog the database (think filehandles and memory usage) needlessly.
It is therefore questionable, in my opinion, what value testing for connectivity condition before checking out a connection from the pool really has. It may be worth testing connection status before a connection is checked in back into the pool, but that can be done implicitly by simply marking the connection as dirty when an SQL hard error (or equivalent exception) arises (unless the API you are using already exposes a
is-bad-like call for you.)I would therefore recommend:
UPDATE
It would appear from your comments that you really really want to ping the connection (I assume that is because you don’t have full control over, or knowledge of, timeout characteristics on the MySQL server or intervening network equipment such as proxies etc.)
In this case you can use
DO 1as an alternative toSELECT 1; it is marginally faster — shorter to parse, and it does not return actual data (although you will get the TCPacks, so you will still do the roundtrip validating that the connection is still established.)UPDATE 2
Regarding Joshua’s post, here’s packet capture traces for various scenarios:
As you can see, except for the fact that the
mysql_pingpacket is 5 bytes instead ofDO 1;‘s 9 bytes, the number of roundtrips (and consequently, network-induced latency) is exactly the same. The only extra cost you are paying withDO 1as opposed tomysql_pingis the parsing ofDO 1, which is trivial.