I fixed an issue on my rails project locally (with postgres config) while adding in database.yml this statement:
test:
prepared_statements: false
As of Feb 19th 2014, heroku no longer overrides database.yml so you can turn off prepared statements in your production and staging (or default) block of the database.yml file as recommended by the latest docs:
default: &default
adapter: postgresql
encoding: unicode
pool: 5
prepared_statements: false
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
pool: <%= ENV['DB_POOL'] || ENV['MAX_THREADS'] || 5 %>
staging:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
pool: <%= ENV['DB_POOL'] || ENV['MAX_THREADS'] || 5 %>
turning off prepared statements decreases performance because postgresql has to replan every query before executing so i do not suggest to turn it off for production servers - especially as rails is notorious for doing many small queries when you don't take really good care about eager loading everything. I suggest indead figuring out how to do restarts in live after each deployment without affecting the availability of your service. I am not a rails guru but i know that it's doable (our company does it exactly like that). Here is a bit more insight into why this is happening https://github.com/rails/rails/issues/12330
We were worried about brittleness and maintaining consistency between staging/production (using DATABASE_URL on Heroku) and development/test (using database.yml/database.example.yml).
Inspired by Rails' tests, we put this in config/initializers/disable_prepared_statements.rb:
ActiveRecord::Base.establish_connection(
ActiveRecord::Base.remove_connection.merge(
:prepared_statements => false
)
)
remove_connection returns a hash of the connection parameters of the connection being removed. This should let any database.yml or DATABASE_URL continue working.
You should just be able to add ?prepared_statements=false to the existing database url and restart your dynos. This worked for us.
heroku config:add DATABASE_URL=[old database url here]?prepared_statements=false
To check that it's set after restarting your server you can open a console and query ActiveRecord::Base.connection_config.
You can pass in a configuration hash to ActiveRecord::Base.establish_connection, in an initializer. For example:
configure :production, :development, :test do
db = URI.parse(ENV['DATABASE_URL']
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:username => db.user,
:password => db.password,
:database => db.path[1..-1],
:encoding => 'utf8',
:prepared_statements => false,
)
end
http://apidock.com/rails/ActiveRecord/Base/establish_connection/class
Recently it seems that Heroku has disabled setting DATABASE_URL using heroku config:set DATABASE_URL=<blah>?prepared_statements=false, giving us back an error " ▸ Cannot overwrite attachment values DATABASE_URL."
In order to resolve this, we added an disabled_prepared_statements.rb initializer in config/ containing:
ActiveRecord::Base.configurations[Rails.env].merge!(prepared_statements: false)