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)