MySQL has a feature that enforces a maximum number of connections, max_user_connections.
When connecting from PHP (and other languages), in the event you exceed that number, my understanding is that your connection will fail with an error stating that you have exceeded the maximum number of connections. Correct?
My preference would be to instead have the connect call wait (up to some timeout limit) for a connection to become available. However, I have not been able to determine a way to do this from reading through the MySQL docs and searching the web.
My concern is that, in the event we have a flood of traffic to our web app that resulted in a large number of concurrent MySQL connection attempts, some of our users scripts will end with an error. Naturally, we could modify the calling code to try to re-connect up to a certain number of times, but it would much cleaner if we could modify the connection attempt itself to handle this, instead of having to wrap every "connect" call in a loop. Additionally, a loop would not result in a real FIFO queue, because each individual calling thread would wait a small period of time and try again, and whether it got a connection would depend on whether, at that particular moment, a connection was available. It would then wait again, and while it was waiting a connection might open and a different thread "further back in line" might grab it.
So, when using any of the PHP APIs to connect to MySQL, is there a way to attempt the connection in "wait until a connection is available" fashion?
MySQL doesn't have any feature to do what you're describing. That is, MySQL has no FIFO (queue) of connections when you hit max_connections
. All connections get an error if they can't get connected immediately.
The closest related thing built into MySQL is the config variable back_log
, which only configures the limit on the number of outstanding connections. That is, the main MySQL thread takes a small amount of time to check for incoming connections, and these stack up in the listen queue, which is before the socket even completes and before MySQL determines if we've got more than max_connections
threads. In fact, you could get a bunch of outstanding connections in the listen queue even if the server is currently far below max_connections
threads.
http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_back_log
Another option is to add HA-Proxy into the mix, because HA-Proxy does have provide queue feature. Here's a blog that explains this more: http://flavio.tordini.org/a-more-stable-mysql-with-haproxy
Frankly, most sites just increase max_connections
until it can handle your typical spikes in traffic, and from there just try to optimize database activity, so connections are short in duration and therefore you have good throughput. It also helps to code your application to connect as late as possible and disconnect as promptly as possible once all queries are done.
If you have an atypical spike in traffic that exceeds max_connections
, then your application will receive an error indicating that. You should code your app to handle such errors gracefully. That is, display as nicely as you can a message like "We're sorry, our load is too great to handle your request at the moment, please try back in a minute." That's at least better than an abrupt white screen, or a stack trace or something.