Force $ rake db:reset Despite Other Users with Postgres [duplicate] - ruby-on-rails

This question already has answers here:
Rails + Postgres drop error: database is being accessed by other users
(20 answers)
Closed 9 years ago.
Is there a way to force a database reset even if Postgres has other users using it. I almost always get this error when I try a $ rake db:reset:
Couldn't drop example_database_name :
#<ActiveRecord::StatementInvalid: PG::Error: ERROR: database "example_database_name" is being accessed by other users DETAIL:
There are 2 other session(s) using the database.

Put this in a file lib/database.rake if you find yourself using db:reset a lot in development.
require 'active_record/connection_adapters/postgresql_adapter'
module ActiveRecord
module ConnectionAdapters
class PostgreSQLAdapter < AbstractAdapter
def drop_database(name)
raise "Nah, I won't drop the production database" if Rails.env.production?
execute <<-SQL
UPDATE pg_catalog.pg_database
SET datallowconn=false WHERE datname='#{name}'
SQL
execute <<-SQL
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = '#{name}';
SQL
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
end
end
end
end
Obviously only designed for use on non-production databases. It will cause all existing db connections to be severed, so the next page load might be an error if unicorn/passenger/pow is pooling db connections. If this happens, a simple page refresh will cause the server to open a new connection and all will be well.

if the connected sessions are from your rails process - you definitely want to stop rails, strange things could occur if you drop and rebuild the db from underneath the running process
anyhow the following can be run from the command line to drop postgres connections
psql -c "SELECT pid, pg_terminate_backend(pid) as terminated FROM pg_stat_activity WHERE pid <> pg_backend_pid();" -d 'example_database_name'

Related

Rails 7 - selecting database with multi-database when calling ActiveRecord::Base.connection.execute

The new multi-database feature is great, however it is unclear to me how you can still execute raw mysql calling ActiveRecord::Base.connection.execute and have it select a specific database in the database.yml file.
this
ActiveRecord::Base.connected_to(role: :reading) do
end
Doesnt accept a database
ActiveRecord::Base.connection.execute always seems to USE the first database in the config file.
thanks
Tried: ActiveRecord::Base.connected_to do ...
doesn't expect a database

Rails - Close current DB connection

I am trying to do some DB experiments in which I reset the DB a few times as part of Rails runner script. Here is a simple example:
`rake db:reset`
puts User.count
`rake db:reset`
This fails with:
PG::ObjectInUse: ERROR: database "my_db" is being accessed by other users
DETAIL: There is 1 other session using the database.
I understand why this happens. The User.count opens a connection so the reset cannot happen. I have tried a few things to close said connection, including calling close and reset_active_connections!, to no avail. Any idea how I can achieve this? Some other pursuits were not fruitful as well, such as trying to close the connection by passing the process ID to psql.
The right call is:
ApplicationRecord.connection_pool.connections.map &:disconnect!
I simply couldn't find the right method the first time, had to read the AR code in more detail to find it.

rails postgres some of the sequence not start from 1

I am using ruby on rails with postgresql database. A weird thing happened that some of the tables_id_seq are not starting from 1, but 980190963. But some of the seq are correctly starting from 1.
The problem is when I tried to insert data into those table which seq not start from 1, unique primary key violation raised occasionally.
--EDIT--
I found that when I do
rake db:migrate test
The problem happens.
If I do
rake db:migrate RAILS_ENV=test
The problem has gone.
If you don't need to keep the data in those tables, you can run the following which will reset the table (THIS WILL REMOVE ANY DATA THERE) and restart the tables id to start at 1. THIS IS ONLY VIABLE IF YOU DON"T NEED THE DATA IN THAT TABLE!
ActiveRecord::Base.connection.execute("TRUNCATE TABLE table_name_here RESTART IDENTITY")
As far as why your tables are starting at that id value I would start by checking your migrations. Maybe somewhere in the code there is an "Alter Sequence" sql statement but again not sure.

ALTER SEQUENCE on rake db:reset db:migrate not working

I'm developing an information system in Ruby on Rails.
I want to hand out following uids to users:
0: root
1-499: system services (server-side)
500: system admin
501-999: external apps (apps that connect through API)
1000+: human users
I have the following migration set up:
class SetUsersAutoincrementValue < ActiveRecord::Migration
def change
execute("ALTER SEQUENCE users_id_seq RESTART WITH 1000")
end
end
The migration works as expected. However, it doesn't if triggered by rake db:reset db:migrate.
What to do?
Thanks
I suppose rake db:migrate:reset.
Try to restart the ruby server (Puma) may help.
I run the SQL command ALTER TABLE directly on DB to change a table id column from INT to BIGINT.
After updating, when inserting big number I got an error out of range for ActiveModel::Type::Integer with limit 4"
After restart ruby server, everything works well.

How to delete everything from all tables without dropping the database [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Truncating all tables in a postgres database
How can I delete all data from all tables without dropping the database?
You can use raw connection object to execute SQL statements:
connection = ActiveRecord::Base.connection
connection.tables.each{|t| connection.execute "TRUNCATE #{t}"}
Use the DatabaseCleaner gem.
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
If you absolutely must have this within a rake task, just wrap it up in one yourself.
For ad-hoc use
Run this statement in the database (Careful! Nukes all your data!):
DO
$func$
BEGIN
EXECUTE (
SELECT 'TRUNCATE TABLE '
|| string_agg(quote_ident(t.tablename), ', ')
|| ' CASCADE'
FROM pg_tables t
WHERE t.schemaname = 'public' -- assuming default schema
);
END
$func$;
The DO command was introduced with PostgreSQL 9.0. You would create a plpgsql function and execute it for older versions.
Compare to the closely related question: Truncating all tables in a Postgres database
For repeated use
It might be simpler (and faster!) to create a "template" database (let's name it my_template) with your vanilla structure and all empty tables. Then go through a DROP / CREATE DATABASE cycle:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
This is extremely fast, because PostgreSQL copies the whole structure on the file level. No concurrency issues or other overhead slowing you down.
You can do a backup of the database with pg_dump and restore only the schema of the database with pg_resotre --schema-only , it deletes all data in all tables.
Exemple:
To backup.
pg_dump --format=c --compress=0 -h localhost mydatabasename > mydump.dmp
To restore only schema information without data.
pg_restore -c --schema-only mydump.dmp | psql -h localhost mydatabasename

Resources