暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

invalid memory alloc request size问题处理

jack 2024-03-11
1579

原因:

数据库产生坏行,常见发生数据库异常断电

解析:

数据库的xlog也就是wal日志可以重用,即将数据库head置为空,然后改名即可重用,在备机启动时,进入redo流程,开始读取wal日志,进行校验,当校验这种被重用的日志时,期望是校验失败,redo结束,然后从新开始写该wal日志,但是因为重用日志只清理了文件头的原因,极小概率在校验时依旧校验成功,然后读取到脏数据,并根据脏数据申请内存,此时申请内存就有概率超过规定的最大申请1g内存的限制,从而导致报错,并退出数据库,于是数据库无法启动成功。

尝试方法一:

自带参数zero_damaged_pages,将这个参数修改为true,但发现仍然是报错,这种方法不会对物理文件作修改,只是把内存上,损坏页面的缓存变为0。如果这个方法解决了报错,请将这表备份出来重新恢复,或者select到另一张表。

尝试方法二:

找出损坏行:

create extension hstore;

CREATE OR REPLACE FUNCTION
  find_bad_row(tableName TEXT)
  RETURNS tid
  as $find_bad_row$
DECLARE
  result tid;
  curs REFCURSOR;
  row1 RECORD;
  row2 RECORD;
  tabName TEXT;
  count BIGINT := 0;
BEGIN
  SELECT reverse(split_part(reverse($1), '.', 1)) INTO tabName;
  OPEN curs FOR EXECUTE 'SELECT ctid FROM ' || tableName;

  count := 1;
  FETCH curs INTO row1;
  WHILE row1.ctid IS NOT NULL LOOP
    result = row1.ctid;
    count := count + 1;
    FETCH curs INTO row1;
    EXECUTE 'SELECT (each(hstore(' || tabName || '))).* FROM '
         || tableName || ' WHERE ctid = $1' INTO row2
         USING row1.ctid;
    IF count % 100000 = 0 THEN
      RAISE NOTICE 'rows processed: %', count;
    END IF;
  END LOOP;

  CLOSE curs;
  RETURN row1.ctid;
  EXCEPTION
    WHEN OTHERS THEN
      RAISE NOTICE 'LAST CTID: %', result;
      RAISE NOTICE '%: %', SQLSTATE, SQLERRM;
  RETURN result;
END
$find_bad_row$
LANGUAGE plpgsql;
js1=# select find_bad_row('public.description');
NOTICE: LAST CTID: (78497,6)
NOTICE: XX000: invalid memory alloc request size 18446744073709551613
find_bad_row
--------------
(78497,6)
(1 row)

js1=# select * from xxxxxxx where ctid = '(78498,1)';
ERROR: invalid memory alloc request size 18446744073709551613
js1=# delete from xxxxxx where ctid = '(78498,1)';

三、CLOB断电损坏

Could not read from file ""_clog/0442"" at offset 243284

伪造文件:

for i in {1..262144}; do printf '\125'; done > committed
ls -l committed
od -xv committed | head
od -xv committed | tail

$ ls -l committed
-rw-r--r-- 1 root root 262144 2009-06-25 11:01 committed

$ od -xv committed  | head
0000000 5555 5555 5555 5555 5555 5555 5555 5555
0000020 5555 5555 5555 5555 5555 5555 5555 5555
0000040 5555 5555 5555 5555 5555 5555 5555 5555
0000060 5555 5555 5555 5555 5555 5555 5555 5555
0000100 5555 5555 5555 5555 5555 5555 5555 5555
0000120 5555 5555 5555 5555 5555 5555 5555 5555
0000140 5555 5555 5555 5555 5555 5555 5555 5555
0000160 5555 5555 5555 5555 5555 5555 5555 5555
0000200 5555 5555 5555 5555 5555 5555 5555 5555
0000220 5555 5555 5555 5555 5555 5555 5555 5555
$ od -xv committed  | tail
0777560 5555 5555 5555 5555 5555 5555 5555 5555
0777600 5555 5555 5555 5555 5555 5555 5555 5555
0777620 5555 5555 5555 5555 5555 5555 5555 5555
0777640 5555 5555 5555 5555 5555 5555 5555 5555
0777660 5555 5555 5555 5555 5555 5555 5555 5555
0777700 5555 5555 5555 5555 5555 5555 5555 5555
0777720 5555 5555 5555 5555 5555 5555 5555 5555
0777740 5555 5555 5555 5555 5555 5555 5555 5555
0777760 5555 5555 5555 5555 5555 5555 5555 5555
1000000

chown postgres.postgres committed
chmod 600 committed
mv -i committed $PGDATA/pg_clog/0442

五、查找损坏的行方法

DO $$
declare
  v_rec record;
BEGIN    
  for v_rec in SELECT * FROM pg_statistic loop
    raise notice ‘Parameter is:‘, v_rec.ctid;
    raise notice ‘Parameter is:’, v_rec;
  end loop;
END;
$$
LANGUAGE plpgsql;delete from pg_statistic where ctid ='(52,3)';
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论