Problem Background
I have an application that runs as a multi-threaded daemon using ActiveRecord on the back-end to aggregate data from multiple data sources into a single database. After investigating reports of this application failing and returning an exception containing the text "too many connections" I chased it up the call stack to discover that it was ActiveRecord's MySQL Adapter that was tossing the exception.
My application behaves in the following way:
- Initialize and use ActiveRecord:Base.establish_connection to configure and connect to the database.
- Service sockets to receive and parse messages.
- Call a function which instantiates an object type based on the ActiveRecord class, then:
- Set the AR object's variables to the data contained in the message.
- Save the object.
- Return; rinse, wash, and repeat.
Inferring from the fact that I was configuring ActiveRecord to connect to MySQL via a UNIX file-system socket and that I was only calling establish_connection once, I was surprised to find that I could be running out of connections at all. After searching and researching I found out that if allow_concurrency is set to true--which is the default if ActiveRecord::Base is instantiated outside of WEBrick, as according to this documentation--rails will and should establish one and only one connection for every class derived from ActiveRecord if and only if a connection does not already exist for a previously instantiated class or ancestor of that class, all the way up to ActiveRecord::Base itself. The problem is this does not seem to be the case.
Careful debugging has shown that AR is attempting to create a new database connection each and every time an ActiveRecord::Base derived class is being instantiated. Since database connections never close, it doesn't take too long before MySQL runs out of connections to offer and ultimately my application begins to fail.
Disabling concurrent connections in the following manner within my application initialization seems to act as a suitable work-around:
ActiveRecord::Base.allow_concurrency = false
ActiveRecord::Base.connection
Resolution Discussion
I would love to help fix this problem and provide a patch, but I don't have a clear understanding on what should be the correct behavior. Specifically:
- How and when should connections to the database be established when concurrency is enabled?
- When concurrency is enabled, how, when and should connections to the database ever close?
Final Notes
Thank you very much! I look forward to hearing how I may help!