PostgreSQL 9.4突然无效的内存分配请求大小

时间:2015-09-21 04:52:53

标签: database postgresql

我正在构建一个网站,用于处理来自商店的excel文件并对其进行操作(合并,查看等)。我使用PostgreSQL 9.4作为数据库,在带有4GB RAM的Centos 6.6 VM上运行。它有3个数据库如下:

  • postgres数据库
  • db_raw,用作数据的占位符。将从网站上传的excel将被解析,数据将存储在此处。该数据库包含几个用于保存处理excel所需数据的表,以及一个用于存储excel数据的大表,当前包含> 140列和近100万行
  • db_processed,这是该网站的主要数据库。它有很少的小表用于网站的操作(用户表,访问列表,日志记录等),以及8个表来存储来自db_raw的已处理的excel数据。 8个表中的每一个都有大约40列和大约一百万行。

数据库运行良好,直到今天早上。我尝试通过pgAdmin和PuTTY连接到db_processed,PostgreSQL给了我这条消息

FATAL:  invalid memory alloc request size 144115188075856068

db_raw工作正常,据我所知,自3天前没有任何改变。我应该怎么做才能再次连接到数据库?

更新:我做了@CraigRinger所说的并重新启动了该服务。我设法连接到数据库,但所有表都消失了:|现在这一直出现在日志中

< 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.

2 个答案:

答案 0 :(得分:1)

这通常表示数据已损坏。我也遇到了这个问题,至少发现了如何解决它的方法。

这里描述了第一种方式:https://confluence.atlassian.com/jirakb/invalid-memory-alloc-request-size-440107132.html
第二个描述如下:http://blog.dob.sk/2012/05/19/fixing-pg_dump-invalid-memory-alloc-request-size/

尽管如此,改善第二种方法的功能以使其完全自动化将是非常酷的。

答案 1 :(得分:1)

这是由损坏的行引起的。

创建一个函数来“检测”损坏的行:

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;

...,然后创建一个“临时表”以存储不良行的ctid:

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

...,然后您只需要删除这些行:

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

...并删除“临时表”:

drop table bad_rows