I accidentally dropped a table from pg_class
and I have the same table present in a different server inside a schema. How do I restore it?
I have tried this
psql -U {user-name} -d {desintation_db} -f {dumpfilename.sql}`
This is what i'm getting -
ERROR: type "food_ingredients" already exists`
HINT: A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type.`
ERROR: relation "food_ingredients" does not exist`
ERROR: syntax error at or near "19411"`
LINE 1: 19411 10405 2074 45.3333333333 0.17550085492131515 NULL NULL...`
ERROR: relation "food_ingredients" does not exist`
food_ingredients
is the table which I dropped from the pg_class.
That's what you get from messing with system catalogs.
The simple and correct answer is “restore from a backup”, but something tells me that that's not the answer you were looking for.
You could drop the type that belongs to the table, all indexes on the table, all constraints, toast tables and so on, but you'd probably forget to drop something or drop something you shouldn't and end up with a bigger mess than before.
Moreover, the table file would be left behind and it would be hard to identify and delete it.
It would be appealing to try and recreate the pg_class
row that you dropped, but you wouldn't be able to create it with the correct oid
since you cannot directly insert a certain oid
or update that column.
You could dump the whole database cluster with pg_dumpall
, create a new cluster with initdb
and restore the backup there, but this might fail because of the data inconsistencies.
Really, the best thing is to restore a backup.
I was able to perform a partial restore using the pg_dirtyread extension.
Initial situation was:
relation "messed_table" does not exist`
The following query provided me the values I had dropped:
SELECT * FROM pg_dirtyread('pg_class'::regclass)
as t(relname name, relnamespace oid, reltype oid, reloftype oid, relowner oid, relam oid, relfilenode oid, reltablespace oid, relpages integer, reltuples real, relallvisible integer, reltoastrelid oid, relhasindex boolean, relisshared boolean, relpersistence "char", relkind "char", relnatts smallint, relchecks smallint, relhasoids boolean, relhaspkey boolean, relhasrules boolean, relhastriggers boolean, relhassubclass boolean, relrowsecurity boolean, relforcerowsecurity boolean, relispopulated boolean, relreplident "char", relispartition boolean, relfrozenxid xid, relminmxid xid, relacl aclitem[], reloptions text[], relpartbound pg_node_tree)
WHERE relname = 'messed_table';
I used the result for performing an INSERT:
INSERT INTO pg_class
(relname,relnamespace,reltype,reloftype,relowner,relam,relfilenode,reltablespace,relpages,reltuples,relallvisible,reltoastrelid,relhasindex,relisshared,relpersistence,relkind,relnatts,relchecks,relhasoids,relhaspkey,relhasrules,relhastriggers,relhassubclass,relrowsecurity,relforcerowsecurity,relispopulated,relreplident,relispartition,relfrozenxid,relminmxid,relacl,reloptions,relpartbound)
VALUES('messed_table',16447,17863,0,10,0,17861,0,0,0,0,0,false,false,'p','r',78,0,false,false,false,false,false,false,false,true,'d',false,1129231::text::xid,1::text::xid,null,null,null);
At this stage executing a SELECT * from messed_table
returned
catalog is missing 78 attribute(s) for relid 26130
So I created a new table messed_table_copy
having the same structure of the messed table.
I exported to a file the pg_attribute
content for the messed_table_copy
table using this query:
Copy (SELECT * FROM pg_attribute WHERE attrelid = (SELECT oid from pg_class WHERE relname LIKE 'messed_table_copy') and attnum > 0) To '/tmp/recover.csv' With CSV DELIMITER ',' HEADER;
I changed the attrelid
value to the relid
value pointed out in the error message and I imported the data from the file again:
COPY pg_attribute(attrelid,attname,atttypid,attstattarget,attlen,attnum,attndims,attcacheoff,atttypmod,attbyval,attstorage,attalign,attnotnull,atthasdef,attidentity,attisdropped,attislocal,attinhcount,attcollation,attacl,attoptions,attfdwoptions) FROM '/tmp/recover.csv' DELIMITER ',' CSV HEADER;
At this stage SELECT count(*) FROM messed_table
worked but a SELECT * FROM messed_table
crashed the database with the following error:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
Performing some queries specifying only a subset of all the available columns I noticed that only selecting certain columns a crash happened. I had been able to recover about 90% of the data, losing the content of some columns. Good luck and remember to never play with the pg_class
table again.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.