Aldibe
Aldibe

Reputation: 1347

PostgreSQL 9.4 suddenly invalid memory alloc request size

I'm building a website which will be used to handle excel files from stores and manipulate them (merging, view, etc.). I'm using PostgreSQL 9.4 for the database, running on Centos 6.6 VM with 4GB RAM. It has 3 databases as follow:

The databases were running fine until this morning. I tried connecting to the db_processed through pgAdmin and PuTTY, and PostgreSQL gave me this message

FATAL:  invalid memory alloc request size 144115188075856068

db_raw works fine, and nothing has been changed since 3 days ago as far as I know. What should I do so I can connect to the database again?

update : I did what @CraigRinger said and restarted the service. I manage to connect to the database, but all the tables are gone :| now this keeps appearing in the log

< 2015-09-21 12:27:22.155 WIB >DEBUG:  performing replication slot checkpoint
< 2015-09-21 12:27:22.158 WIB >LOG:  request to flush past end of generated WAL; request 46/9E0981D8, currpos 46/771C69B0
< 2015-09-21 12:27:22.158 WIB >CONTEXT:  writing block 2 of relation base/18774/12766
< 2015-09-21 12:27:22.158 WIB >ERROR:  xlog flush request 46/9E0981D8 is not satisfied --- flushed only to 46/771C69B0
< 2015-09-21 12:27:22.158 WIB >CONTEXT:  writing block 2 of relation base/18774/12766
< 2015-09-21 12:27:22.158 WIB >WARNING:  could not write block 2 of base/18774/12766
< 2015-09-21 12:27:22.158 WIB >DETAIL:  Multiple failures --- write error might be permanent.

Upvotes: 9

Views: 24332

Answers (1)

Christian
Christian

Reputation: 7320

It is caused by corrupted rows.

Create a function do "detect" the rows that are corrupted:

CREATE OR REPLACE FUNCTION is_bad_row(tableName TEXT, tabName TEXT, tidInitial tid)
RETURNS integer 
as $find_bad_row$
BEGIN
    EXECUTE 'SELECT (each(hstore(' || tabName || '))).* FROM ' || tableName || ' WHERE ctid = $1' USING tidInitial; 
    RETURN 0;
    EXCEPTION
        WHEN OTHERS THEN
        RAISE NOTICE '% = %: %', tidInitial, SQLSTATE, SQLERRM;
        RETURN 1;
END
$find_bad_row$
LANGUAGE plpgsql;

... and then create a "temp table" to store the ctid of the bad rows:

create table bad_rows as 
SELECT ctid as row_tid
FROM your_schema.your_table
where is_bad_row('your_schema.your_table', 'your_table', ctid) = 1

... and after that you just need to delete those rows:

delete from your_schema.your_table where ctid in (select row_tid from bad_rows)

... and remove the "temp table":

drop table bad_rows

Upvotes: 5

Related Questions