ActiveRecord.connection_pool separate connections for each p

Hi!

I am creating an ActiveRecord connection. In my code I am forking
multiple processes which uses this ActiveRecord connection.
However when the forked process ends it release the ActiveRecord
Connection and I get the exception Mysql::Error: MySQL server has gone
away

I can catch the exception and establish the ActiveRecord connection
again, but this would involve a number or rescue statements and it would
be cumbersome.

Is it possible that I can use a connection from the connection pool and
then, each forked process uses the separate connection within the
process and return it back to the pool once i am through with it?

Thanks
Glen

Code : - fold - unfold

   1. require "rubygems"
   2. require "active_record"
   3.
   4. ActiveRecord::Base.establish_connection(
   5. :adapter => "mysql",
   6. :username => "root",
   7. :database => "test_dev",
   8. :pool => 5 # Setting the pool size to 5
   9. )
  10.
  11. class TestDb < ActiveRecord::Base
  12. set_table_name "test_dbs"
  13. end
  14.
  15.
  16. puts "Parent Process - the first record of the db is
#{TestDb.first.id}"
  17.
  18. Process.fork do
  19. puts "In the forked process the first record id is
#{TestDb.first.id}"
  20. # The forked process releases the connection here.
  21. end
  22.
  23. sleep(2) # This is just to simulate exit of the process first and
releasing the connection.
  24.
  25. # No ActiveRecord connection as it has been released by the forked
process.
  26. puts "Parent Process the first record id is #{Testdb.first.id}"

thank anyway

···

--
Posted via http://www.ruby-forum.com/.

I don't believe this will work as it stands. If you create a pool of 5
connections and then fork, each child process will have a copy of the
same pool. When one process 'takes' the first connection, the other
children won't be updated, so every other process will also 'take' the
same connection out of the pool. As a result, they'll all end up sharing
the same mysql connection socket, which is very dangerous here (e.g.
commands from the two processes could be intermingled, and responses
could be delivered to the wrong client)

As for when a child exits: this has been reported here before. It seems
that the mysql client sends a 'close' message down the socket in its
finalizer; that is, when the connection object is destroyed. So if two
processes really are sharing the same socket, when one terminates, the
server will be told to disconnect, so the other process will see a
disconnection too.

So you need to either:

1. Rewrite your code to use Ruby threads, instead of forking. The
connection pool will be fine then.

2. Fork first, *then* connect to the database. Then each process will
have its own separate connection.

If you are worried about the overhead of reconnecting frequently, then
start N worker processes, each of which opens a connection, and then
loops around picking jobs from a Queue.

HTH,

Brian.

···

--
Posted via http://www.ruby-forum.com/.

Virendra Negi wrote:

Hi!

I am creating an ActiveRecord connection. In my code I am forking
multiple processes which uses this ActiveRecord connection.
However when the forked process ends it release the ActiveRecord
Connection and I get the exception Mysql::Error: MySQL server has gone
away

I also wrestled with this problem for a long time. The problem is that when the mysql connection is finalized, either because the process exits or due to garbage collection, it sends a "close" message to the server. The parent process, which uses the same connection, suddenly finds the server is no longer there. Here is the solution that I found:

   Process.fork{
     ActiveRecord::Base.active_connections.values.each(&:connect)
     #do your stuff here
   }

This code establishes a new connection for each forked child, but without shutting down the connection inherited from the parent.

Daniel