PostgreSQL DELETE FROM이 실패하고 '오류 : 보이지 않는 튜플을 삭제하려고했습니다'


25

오류

잘못된 타임 스탬프가 포함 된 튜플을 삭제하려고합니다.

DELETE FROM comments WHERE date > '1 Jan 9999' OR date < '1 Jan 2000' OR date_found > '1 Jan 9999' OR date_found < '1 Jan 2000';

끝나다

ERROR:  attempted to delete invisible tuple

2009 년 메일 링리스트 OP는 고정했다 동일한 오류 메시지, 논의,하지만 나는 그가 그것을 또는 무엇이 오류로 이어졌다 수있는 방법에 아무런 설명을 찾을 수 없습니다.

Google에 대한 조회수 부족과 PostgreSQL에 대한 제한된 지식으로 인해 무기력합니다.

부패의 원인

OS 커널이 패닉 상태 일 때 데비안 8에서 PostgreSQL 9.5.5 서버 ( ~ 4TB 데이터, 모든 기본 설정, 메모리 제한을 제외한 모든 기본 설정 )를 실행했습니다. 아마도 스왑이있는 / dev / md1을 다시 빌드하는 동안 가능했습니다. 그 전에 PostgreSQL은 400GB 로그 파일로 거의 모든 디스크 공간을 차지했습니다. OS는 다시 부팅되지 않았으며 디스크 검사는 정상적으로 완료되었으므로 LiveCD에서 부팅하여 각 블록 장치를 이미지에 백업했습니다. / dev / md2에서 / 디렉토리를 성공적으로 재 구축했으며 fsck가 깨끗한 파일 시스템을 표시했으며 PGDATA 폴더를 외부 HDD에 백업했습니다.

내가 복구를 시도한 것

md 장치를 포맷하고 새로운 postgresql-9.5와 함께 OS를 다시 설치 한 후 PostgreSQL 서버를 중지하고 PGDATA 폴더를 postgres 사용자에게 옮기고 서버를 시작했으며 서버를 시작했습니다.

최대한 빨리 시작한으로 pg_dumpall, 그것은 죽었다

Error message from server: ERROR:  timestamp out of range

나는 자연스럽게 문제가되는 튜플을 삭제하려고 시도했지만 동일한 invisible tuple오류가 반복해서 발생했습니다.

내가 시도한 것

먼저 손상된 페이지로 인해 DELETE 쿼리가 실패 했으므로 다음 설정을 지정했습니다.

zero_damaged_pages = on
ignore_system_indexes = on
enable_indexscan = off
enable_bitmapscan = off
enable_indexonlyscan = off

이제 동일한 쿼리를 다시 실행하면 서버가 동일한 페이지를 반복해서 제로화하지만 의미가 무엇인지 알지 못합니다.

invalid page in block 92800 of relation base/16385/16443; zeroing out page

정의되지 않은 순서로 다음을 시도했습니다.

  • pg_resetxlog -D $PGDATA 오류나 메시지없이 작업을 수행함
  • pkey 제약 조건을 포함한 모든 인덱스를 삭제했습니다.
  • CREATE TABLE aaa AS (SELECT * FROM comments);리드에 Segmentation fault

    heap_deform_tuple (tuple=tuple@entry=0x7f0d1be29b08, tupleDesc=tupleDesc@entry=0x7f0d1a35abe0, values=values@entry=0x7ffd57a5beb0, isnull=isnull@entry=0x7ffd57a65af0 "\001\001") 재현 가능하며 ~ 9GB 코어 덤프를 남깁니다.

  • SELECT COUNT(*) from comments;VACUUM comments;완료가 허용 되면 다른 테이블에서 동일한 트릭이 작동하지 않습니다.
  • SELECT COUNT(*) from photos;그리고 VACUUM photos;지금과 죽으면 ERROR: MultiXactId 302740528 has not been created yet -- apparent wraparound다른 오류가 더 이상 팝업하지 않는 모든 테이블이 하나 개의 서식지 -.

생각

  • DB가 (많은에 의해 타격을 받고되었다 가능성이 중복 )으로 기록 ON CONFLICT DB는하고 있었다 VACUUM나는 그것이에 문제를 일으키는 것을 그것의 왼쪽 무엇을 믿고, 커널 패닉이 발생하는 경우 nonexistent MultiXactIdsinvisible tuple
  • 2 년 이상 크롤러를 사용하여 데이터를 수집했으며 일부 데이터를 잃어도 괜찮습니다.
  • 이제 백업을합니다
  • 테이블 또는 트리거간에 관계 제한이 없습니다.

다음은 현재 pg_controldata 출력입니다.

pg_control version number:            942
Catalog version number:               201510051
Database system identifier:           6330224129664261958
Database cluster state:               in production
pg_control last modified:             Thu 08 Dec 2016 01:06:22 AM EET
Latest checkpoint location:           1562/8F9F8A8
Prior checkpoint location:            1562/8F7F460
Latest checkpoint's REDO location:    1562/8F9F8A8
Latest checkpoint's REDO WAL file:    000000010000156200000008
Latest checkpoint's TimeLineID:       1
Latest checkpoint's PrevTimeLineID:   1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID:          0/40781255
Latest checkpoint's NextOID:          67798231
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        615
Latest checkpoint's oldestXID's DB:   1
Latest checkpoint's oldestActiveXID:  0
Latest checkpoint's oldestMultiXid:   1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint:            Thu 08 Dec 2016 01:06:22 AM EET
Fake LSN counter for unlogged rels:   0/1
Minimum recovery ending location:     0/0
Min recovery ending loc's timeline:   0
Backup start location:                0/0
Backup end location:                  0/0
End-of-backup record required:        no
wal_level setting:                    minimal
wal_log_hints setting:                off
max_connections setting:              100
max_worker_processes setting:         8
max_prepared_xacts setting:           0
max_locks_per_xact setting:           64
track_commit_timestamp setting:       off
Maximum data alignment:               8
Database block size:                  8192
Blocks per segment of large relation: 131072
WAL block size:                       8192
Bytes per WAL segment:                16777216
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        1996
Size of a large-object chunk:         2048
Date/time type storage:               64-bit integers
Float4 argument passing:              by value
Float8 argument passing:              by value
Data page checksum version:           0

업데이트

  • ( 2016 년 12 월 9 일 ) 존재하지 않는 MultiXactIds 에 대해 읽는 동안 충돌이 발생했을 때 데이터베이스가 운영로드 상태가 아니었지만 수동 VACUUM요청 을 처리하고 있음을 기억했습니다. 디스크에 3 %의 공간 만 남았다는 것을 알게 된 후 웹 서버와 크롤러를 오프라인으로 전환했습니다. /var/log큰 파일 을 확인해야 했지만 실수로 PostgreSQL을 비난하고 시도했지만 VACUUM FULL장치에 남은 공간이 부족하여 중단 된 것을 발견했습니다. 그래서 나는 보통의 VACUUM을 시작했고 그것을 그대로 두었습니다.
  • ( 2016 년 12 월 14 일 ) Github에서 9.5 개의 PostgreSQL 소스를 다운로드하고 heapam.cmultixact.c의 블록을 주석 처리 하고 이러한 오류가 발생하지 않도록하기 위해 컴파일했습니다. 그러나 서버는 APT에서 사용했던 것과 동일한 플래그로 구성되어야하기 때문에 시작되지 않았습니다. 약 47 개의 플래그가 있으며, 각각 분명하지 않은 이름으로 종속성을 요구하므로 그 아이디어를 포기했습니다.
  • ( 2016 년 12 월 16 일 ) 관련 페이지를 0으로 만들어 유효하지 않은 타임 스탬프가있는 튜플을 제거하는 방법을 찾았습니다. 먼저 다음 옵션을 설정했습니다 psql.

    \set FETCH_COUNT 1
    \pset pager off

    그런 다음 SELECT ctid, * FROM comments;. 그렇게 ctid하면 쿼리가 종료되기 전에 잘못된 튜플을 뱉어냅니다 . 그런 다음 해당 페이지를 0으로 채우십시오. dd if=/dev/zero of=/var/lib/postgresql/9.5/main/base/16385/16443 bs=8K seek=92803 count=1 conv=notrunc그러나이 방법으로 0으로 설정된 각 페이지는 이전 페이지를 중단하여 페이지에 16442잘못된 타임 스탬프가있는 튜플이 생깁니다. 내가 뭘 잘못하고 있는지 잘 모르겠다.

  • ( 2016 년 12 월 16 일 ) pg_dump -Fc --table photos vw > photos.bak1.3GB ( 아마도 800GB 중 )를 쓴 후 세그먼트 오류가 발생했습니다 . 서버 로그는 다음과 같습니다.

    2016-12-16 18:48:05 EET [19337-2] LOG:  server process (PID 29088) was terminated by signal 11: Segmentation fault
    2016-12-16 18:48:05 EET [19337-3] DETAIL:  Failed process was running: COPY public.photos (id, owner_id, width, height, text, date, link, thumb, album_id, time_found, user_id, lat, long) TO stdout;
    2016-12-16 18:48:05 EET [19337-4] LOG:  terminating any other active server processes
    2016-12-16 18:48:05 EET [19342-2] WARNING:  terminating connection because of crash of another server process
    2016-12-16 18:48:05 EET [19342-3] DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
    2016-12-16 18:48:05 EET [19342-4] HINT:  In a moment you should be able to reconnect to the database and repeat your command.
    2016-12-16 18:48:05 EET [19337-5] LOG:  all server processes terminated; reinitializing
    2016-12-16 18:48:06 EET [29135-1] LOG:  database system was interrupted; last known up at 2016-12-14 22:58:59 EET
    2016-12-16 18:48:07 EET [29135-2] LOG:  database system was not properly shut down; automatic recovery in progress
    2016-12-16 18:48:07 EET [29135-3] LOG:  invalid record length at 1562/A302F878
    2016-12-16 18:48:07 EET [29135-4] LOG:  redo is not required
    2016-12-16 18:48:07 EET [29135-5] LOG:  MultiXact member wraparound protections are now enabled
    2016-12-16 18:48:07 EET [19337-6] LOG:  database system is ready to accept connections
    2016-12-16 18:48:07 EET [29139-1] LOG:  autovacuum launcher started

    짧은 스택 추적은 다음과 같습니다.

    #0  pglz_decompress (source=source@entry=0x7fbfb6b99b13 "32;00/0ag4d/Jnz\027QI\003Jh3A.jpg", slen=<optimized out>,
        dest=dest@entry=0x7fbf74a0b044 "", rawsize=926905132)
    #1  0x00007fc1bf120c12 in toast_decompress_datum (attr=0x7fbfb6b99b0b)
    #2  0x00007fc1bf423c83 in text_to_cstring (t=0x7fbfb6b99b0b)

    나는 그것을 해결하는 방법을 모른다.

  • ( 2016 년 12 월 29 일 ) 나는 SELECT * FROM tablename LIMIT 10000 OFFSET 0오프셋을 증가시키고 죽은 튜플 주위를 좁히는 유틸리티를 작성했으며 , 튜플을 제외하고 로컬 컴퓨터의 데이터를 성공적으로 복제했습니다 ( 수동으로 손상된 것으로 생각 합니다 ). 서버가 다시 시작될 때까지 기다려야합니다. 그러나 RAID에 충분한 공간이없고 slowdisk8TB HDD에 테이블 스페이스 를 만들었습니다 . 시도 할 때 CREATE DATABASE vwslow WITH TABLESPACE slowdisk오류가 발생하지 않습니다.

    2016-12-29 02:34:13 EET [29983-1] LOG:  request to flush past end of generated WAL; request 950412DE/114D59, currpos 1562/A3030C70
    2016-12-29 02:34:13 EET [29983-2] CONTEXT:  writing block 58368001 of relation base/16385/16473
    2016-12-29 02:34:13 EET [29983-3] ERROR:  xlog flush request 950412DE/114D59 is not satisfied --- flushed only to 1562/A3030C70
    2016-12-29 02:34:13 EET [29983-4] CONTEXT:  writing block 58368001 of relation base/16385/16473
    2016-12-29 02:34:13 EET [30005-44212] postgres@vw ERROR:  checkpoint request failed
    2016-12-29 02:34:13 EET [30005-44213] postgres@vw HINT:  Consult recent messages in the server log for details.
    2016-12-29 02:34:13 EET [30005-44214] postgres@vw STATEMENT:  CREATE DATABASE vwslow WITH TABLESPACE slowdisk;

    수동 CHECKPOINT으로 동일한 오류가 발생했습니다.

    서버를 다시 시작하면 검사 점 오류가 사라지고 도구를 실행할 수 있습니다. 내 질문에 대답하고 코드가 작동하면 게시하십시오.


wiki.postgresql.org/wiki/Corruption과 같은 다른 작업을하기 전에이 내용을 읽고 행동 하십시오 . 조금 늦게 보이지만. 디스크 문제 / RAID 재구성이 근본 원인이라고 생각합니다.
Craig Ringer

resetxlog 등을 수행하기 전에 데이터 디렉토리의 사본을 유지 했습니까?
Craig Ringer

datadir 자체는 아니지만 원시 디스크 이미지를 안전한 곳으로 옮겨 왔습니다. RAID를 재 구축했기 때문에 문제가 없습니다.
Kai

1
@CraigRinger 이것에 대한 답변을 하시겠습니까? 당신은 아마도 Postgres 태그로 대답하고 문제에 대해 유용한 것을 말할 수있는 소수의 사용자 중 하나 일 것입니다. 거의 할 수없는 것 같습니다.
ypercubeᵀᴹ

4
당신은 이것에 대한 답을 찾지 못할 것입니다. Erwin이 도와 드릴 수 있습니다. 부끄러워서 irc.freenode.net/#postgresql에서 David Fetter 또는 AndrewSW / RhodiumToad를 찾으십시오. 그들이 찾은 것을 우리에게 (dba.se) 알려주십시오. 데이터베이스에 대한 전체 액세스 권한이 필요한 유료 컨설팅 작업이 될 것 같습니다. developer.postgresql.org/~adunstan linkedin.com/in/davidfetter 나는 그 녀석 들이나 그들의 회사와 관계가 없다. 그러나 그것들은 내가 그 독재에서 벗어나기 위해 개인적으로 신뢰하는 유일한 것입니다.
Evan Carroll

답변:


2

글쎄, 난의 복구 프로세스를 자동화 관리해야 SELECT하고 INSERT INTO범위를 생략하고 서버가 충돌 대기합니다. 먼저 Node에서 코드를 작성했습니다.에서 손상되지 않은 데이터를 추출 comments했으며 계속 진행 중입니다.

어제 내가 여기 Golang을 시도하기로 결정하고, 한 바둑 코드와의 repo입니다 : https://github.com/kaivi/pg_ripper 내가 정말 주위에 나쁜 튜플을 작동하므로 곧 업데이트하고, 단지 전체에 포기하지 않을 것이다 하나를 포함하는 범위.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.