Postgres doesn't reclaim space after failed transaction [duplicate] - postgresql

I have a situation in which summing the size of the tables in a tablespace (using pg_class among others) reveals that there is 550G of datafiles in a particular tablespace in a particular database.
However, there is 670G of files in that directory on the server.
FWIW, I don't know how that can be. No files have been written to that directory via any mechanism other than Postgres. My best guess is perhaps the database crashed while an autovacuum was going on, leaving orphan files laying around...does that sound plausible?)
SO, I've worked out a way, by reading the contents of a ls command into the database, strip off the numeric extensions for tables > 1G in size, and compare them with the contents of pg_class, and have, in fact, found about 120G of files not reflected in pg_class.
My question is, is it safe for me to delete these files, or could they be in active use by the database but not reflected in pg_class?

Do not manually delete files in the PostgreSQL data directory.
This is not safe and will corrupt your database.
The safe way to purge any files that don't belong to the database is to perform a pg_dumpall, stop the server, remove the data directory and the contents of all tablespace directories, breate a new cluster with inindb and restore the dump.
If you want to investigate the issue, you could try to create a new tablespace and move everything from the old to the new tablespace. I will describe that in the rest of my answer.
Move all the tables and indexes in all databases to the new tablespace:
ALTER TABLE ALL IN TABLESPACE oldtblsp SET TABLESPACE newtblsp;
ALTER INDEX ALL IN TABLESPACE oldtblsp SET TABLESPACE newtblsp;
If oldtblsp is the default tablespace of a database:
ALTER DATABASE mydb SET TABLESPACE newtblsp;
Then run a checkpoint:
CHECKPOINT;
Make sure you forgot no database:
SELECT datname
FROM pg_database d
JOIN pg_tablespace s
ON d.dattablespace = s.oid
WHERE s.spcname = 'oldtblsp';
Make sure that there are no objects in the old tablespace by running this query in all databases:
SELECT t.relname, t.relnamespace::regnamespace, t.relkind
FROM pg_class t
JOIN pg_tablespace s
ON t.reltablespace = s.oid
WHERE s.spcname = 'oldtblsp';
This should return no results.
Now the old tablespace should be empty and you can
DROP TABLESPACE oldtblsp;
If you really get an error
ERROR: tablespace "tblsp" is not empty
there might be some files left behind.
Delete them at your own risk...

Related

Create tablespace with IMP Oracle10

friends,
I have a .dump file of oracle 10G that I have to restore with IMP in oracle 11G. but I don't know how to do it so that you don't put the tables inside the tablespace of the system.
The command I'm using is
imp system/passw file=backup_dpz.dmp fromuser=pepe touser=mario
The problem is that the origin has the tables in the tablespace of system and I want that the destiny has it inside the tablespace of mario.
Thank you

What happens after a "DROP DATABASE postgres"

I have a funny question about PostgreSQL database: What happens if the postgres database is dropped?
dropdb postgres worked.
createdb postgres worked too.
psql worked.
But I thought the users would be lost. Yet the old users are still there.
So where are the users stored for the database and which implications does dropping the postgres database have?
PostgreSQL metadata are stored in catalog tables, which are in the pg_catalog schema. These are accessible like regular views and tables.
There are shared system catalog tables which are shared between all databases. These tables are not affected when databases are dropped.
pg_authid, the table where the users are stored, is one of those shared catalogs. This is because in PostgreSQL, users don't belong to a database, but to the whole database cluster.
You can list all shared catalog tables like this:
SELECT relname FROM pg_class
WHERE relisshared AND relkind = 'r';
In the documentation you can find more information about the system catalogs.
When connecting to a Postgres server, you always need to specify which database you want to connect to.
When you set up a new server, you need something to connect to before you can run your first CREATE DATABASE statement.
That's all the postgres database is: a dummy database to use as a connection target for admin commands. There's no data in there, and you're free to drop it and use a different one instead (though whoever inherits your system will probably not thank you for it...).
As gil.fernandes said in his answer, server-wide objects like users are accessible from every database, but aren't stored inside any database in particular.

pg_restore --clean is not dropping and clearing the database

I am having an issue with pg_restore --clean not clearing the database.
Or do I misunderstand what the --clean does, I am expecting it to truncate the database tables and reinitialize the indexes/primary keys.
I am using 9.5 on rds
This is the full command we use
pg_restore --verbose --clean --no-acl --no-owner -h localhost -U superuser -d mydatabase backup.dump
Basically what is happening is this.
I do a nightly backup of my production db, and restore it to an analytics db for the analyst to churn and run their reports.
I found out recently that the rails application used to view the reports was complaining that the primary keys were missing from the restored analytics database.
So I started investigating the production db, the analytics db etc. Which was when I realized that multiple rows with the same primary key existed in the analytics database.
I ran a few short experiments and realized that every time the pg_restore script is run it inserts duplicate data into the tables, this leads me to think that the --clean is not dropping and restoring the data. Because if I were to drop the schema beforehand, I don't get duplicate data.
To remove all tables from a database (but keep the database itself), you have two options.
Option 1: Drop the entire schema
You will need to re-create the schema and its permissions. This is usually good enough for development machines only.
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Applications usually use the "public" schema. You may encounter other schema names when working with a (legacy) application's database.
Note that for Rails applications, dropping and recreating the database itself is usually fine in development. You can use bin/rake db:drop db:create for that.
Option 2: Drop each table individually
Prefer this for production or staging servers. Permissions may be managed by your operations team, and you do not want to be the one who messed up permissions on a shared database cluster.
The following SQL code will find all table names and execute a DROP TABLE statement for each.
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; -- DROP TABLE IF EXISTS instead DROP TABLE - thanks for the clarification Yaroslav Schekin
END LOOP;
END $$;
Original:
https://makandracards.com/makandra/62111-how-to-drop-all-tables-in-postgresql

PostgreSQL pg_dumpall Loses Schemas

I have a postgres database and I'm trying to use pg_dumpall to create the full script to reproduce my database (also using github to keep track of versions of the dump file).
My question is, why does pg_dumpall lose my database schemas? For instance, I have a schema called "go1". My pg_dumpall script should produce a file with "go1.users" for instance for my users table in schema "go1". But the dump file only produces "users". It loses the schema name.
Is there a way for pg_dumpall to preserve the schemas in the dump file?
It does not lose it. View the generated file - you will find search_path before creating schema objects, like:
...
SET search_path = instruction, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: file; Type: TABLE; Schema: instruction; Owner: postgres
--
CREATE TABLE file (
details jsonb,
...
would mean it will create instruction.file table

Store postgres database at some other location other than data folder

Is there any way of storing database other than the fixed data directory in postgres? I have a situation where I need to store database at any location irrespective of data directory.
You can add a tablespace.
A tablespace is basically a location to store databases and/or tables. You create a tablespace using CREATE TABLESPACE:
CREATE TABLESPACE mytablespace LOCATION '/path/to/some/location';
You can then create tables directly in that tablespace:
CREATE TABLE whatever (thing integer) TABLESPACE mytablespace;
Or set the default tablespace:
SET default_tablespace = mytablespace;
You can also set the default tablespace at database creation time:
CREATE DATABASE mydatabase TABLESPACE mytablespace;
You are looking for the 'Data Directory' in linux for example its in
/usr/local/pgsql/data
if you install from source code. Each distribution is different though, try reading up on
File Locations in postgres and Creating a Database Cluster
also try using the query
show data_directory;
in windows try looking around
C:\Program Files (x86)\PostgreSQL\[VERSION]\data\global