# If your workers are inactive for a long period of time, they'll lose | |
# their MySQL connection. | |
# | |
# This hack ensures we re-connect whenever a connection is | |
# lost. Because, really. why not? | |
# | |
# Stick this in RAILS_ROOT/config/initializers/connection_fix.rb (or somewhere similar) | |
# | |
# From: | |
# http://coderrr.wordpress.com/2009/01/08/activerecord-threading-issues-and-resolutions/ | |
module ActiveRecord::ConnectionAdapters | |
class MysqlAdapter | |
alias_method :execute_without_retry, :execute | |
def execute(*args) | |
execute_without_retry(*args) | |
rescue ActiveRecord::StatementInvalid => e | |
if e.message =~ /server has gone away/i | |
warn "Server timed out, retrying" | |
reconnect! | |
retry | |
else | |
raise e | |
end | |
end | |
end | |
end |
This comment has been minimized.
This comment has been minimized.
My testing indicates that it does not. I'm using mysql2 |
This comment has been minimized.
This comment has been minimized.
Do you have any generic code which is DB independent? Like for oracle. |
This comment has been minimized.
This comment has been minimized.
It's not working on a Rails 3.0.7 project. It says it can not find execute method to alias. Any ideas? |
This comment has been minimized.
This comment has been minimized.
I'm getting a stack level too deep error with this patch and Rails 3.0.7, Ruby 1.9.2-p0. I'll check the forks for an improved version. |
This comment has been minimized.
This comment has been minimized.
If you're using the mysql2 gem (the current default), you need to change line 13 to the following: class Mysql2Adapter |
This comment has been minimized.
This comment has been minimized.
Hey there, isn't the "reconnect" option on the database config file supposed to do the exact same thing? |
This comment has been minimized.
This comment has been minimized.
Supposedly reconnect true in the database.yml file will drop other environment configs such as utf8 when it reconnects. Did you ever figure out why the execute method is undefined? Having the same issue. |
This comment has been minimized.
This comment has been minimized.
Is there any reason to use this in applications using ActiveRecord::Base.connection_handler.verify_active_connections! I'm just wondering if these kinds of exceptions still crop up for people and reconnect code like this is necessary when the above technique is used to preemptively nuke stale connections from the connection pools? |
This comment has been minimized.
This comment has been minimized.
whith mysql2 gem, line 18 becomes : rescue Mysql2::Error => e |
This comment has been minimized.
This comment has been minimized.
If someone is gettting a "stack level too deep", it's because Rails is requiring the initializer multiple times. I made a GIST with the correction (and supporting Mysql2 too) |
This comment has been minimized.
This comment has been minimized.
@twinge +1for the Mysql2Adapter fix. |
This comment has been minimized.
This comment has been minimized.
I found that this fix caused me a whole lot of trouble with data integrity when I upgraded to Rails 3.1 from 2.3. I don't know what changed between the two versions, but basically, my class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
end
# ...
User.transaction do
u = User.create!
sleep(10)
p = Post.new
p.user = u
p.save!
end I found that a post row would be created with I think |
This comment has been minimized.
This comment has been minimized.
@agibralter: I did some reading on |
This comment has been minimized.
This comment has been minimized.
@ryansch Interesting -- no I haven't noticed it yet. I guess I could set up an example to test it out though... I'm a bit pressed for time right now though so I may not get around to it for a bit. |
This comment has been minimized.
This comment has been minimized.
We tried the connection fix on a site that is running on Rails2.3.14 with a lot of traffic and run into all kind of strange locking issues on the database. Once we removed the fix, it was all fine again. Can't really explain why this happend. So.. I have been looking for alternative solutions. I have seen people who suggested to add ActiveRecord::Base.verify_active_connections! to your perform. I used an alternative approach by using the after_fork hook inside resque.rb in the config/initializers folder.
This seems to work fine. I wonder why other people are not suggesting this simple approach. Am I missing something? |
This comment has been minimized.
This comment has been minimized.
I ended up doing the following. module BaseJob
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def perform(*args)
ActiveRecord::Base.verify_active_connections!
end
end
end class FooJob
include BaseJob
@queue = :foo_queue
def self.perform(arg)
super
foo_stuff
end
end @mcjansen - Your after_fork solution might be a cleaner way to get this done. |
This comment has been minimized.
This comment has been minimized.
Turns out there is already a plugin that is using the after_fork approach: |
This comment has been minimized.
This comment has been minimized.
I had a bit trouble with the gist when migrating to mysql2 adapter. After checking the rails code I found out that the rails team implemented an AbstractMysqlAdapter so I changed the gist as follows. This should work with mysql and mysql2 adapter, right? Original class MysqlAdapter New class AbstractMysqlAdapter |
This comment has been minimized.
This comment has been minimized.
Because the resque-ensure-connected gem did not solved my issue when the SQL server goes down a longer time I added this gem. I'm open for discussions: https://github.com/dei79/mysql_stay_connected |
This comment has been minimized.
This comment has been minimized.
This should do the trick: Resque.after_fork do
clear_active_connections!
end This would work both before & after forking the child, since it wouldn't close active connections, but it would check everything back in to the connection pool, and checking back out from the pool verifies the connections. |
This comment has been minimized.
This comment has been minimized.
Oops -- that should have been: Resque.after_fork do
ActiveRecord::Base.clear_active_connections!
end |
This comment has been minimized.
reconnect: true not solve that?