Kesalahannya
Mencoba menghapus tupel berisi cap waktu yang tidak valid dengan
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';
berakhir di
ERROR: attempted to delete invisible tuple
Ada milis dari 2009 yang membahas pesan kesalahan yang sama persis, di mana OP memperbaikinya, tapi saya tidak menemukan penjelasan bagaimana dia melakukannya atau apa yang mungkin menyebabkan kesalahan ini.
Saya tidak berdaya karena kurangnya hit di Google dan pengetahuan saya yang terbatas tentang PostgreSQL.
Apa yang menyebabkan korupsi
Saya memiliki server PostgreSQL 9.5.5 ( ~ data 4TB, semua pengaturan default, kecuali untuk batas memori yang ditingkatkan ) yang berjalan di Debian 8, ketika kernel OS panik - mungkin saat membangun kembali / dev / md1 di mana swap berada. Sebelum itu, PostgreSQL menghabiskan hampir semua ruang disk dengan file log 400GB. OS tidak pernah boot lagi, cek disk OK, jadi saya sudah boot dari LiveCD dan mencadangkan setiap perangkat blok ke gambar, untuk berjaga-jaga. Saya telah berhasil membangun kembali / direktori dari / dev / md2, fsck menunjukkan sistem file yang bersih, dan saya telah membuat cadangan folder PGDATA ke HDD eksternal.
Apa yang saya lakukan untuk mencoba pemulihan
Setelah saya memformat perangkat md dan menginstal ulang OS bersama dengan postgresql-9.5 yang baru, saya telah menghentikan server PostgreSQL, memindahkan dan membagi folder PGDATA ke pengguna postgres, dan memulai server - semuanya tampak baik-baik saja, tidak ada kesalahan.
Begitu saya mulai pg_dumpall
, ia mati bersama
Error message from server: ERROR: timestamp out of range
Saya secara alami mencoba untuk menghapus tuple yang menyinggung, hanya untuk berakhir dengan invisible tuple
kesalahan yang sama berulang kali.
Hal yang saya coba
Pertama, DELETE kueri gagal karena laman rusak, jadi saya telah menetapkan pengaturan berikut:
zero_damaged_pages = on
ignore_system_indexes = on
enable_indexscan = off
enable_bitmapscan = off
enable_indexonlyscan = off
Sekarang saya perhatikan bahwa ketika saya menjalankan kueri yang sama lagi, server nol keluar halaman yang sama berulang-ulang, tidak yakin apa artinya:
invalid page in block 92800 of relation base/16385/16443; zeroing out page
Saya sudah mencoba mengikuti dalam urutan yang tidak ditentukan:
pg_resetxlog -D $PGDATA
melakukan tugasnya tanpa kesalahan atau pesan- Menghapus semua indeks termasuk batasan pkey
CREATE TABLE aaa AS (SELECT * FROM comments);
mengarah keSegmentation fault
atasheap_deform_tuple (tuple=tuple@entry=0x7f0d1be29b08, tupleDesc=tupleDesc@entry=0x7f0d1a35abe0, values=values@entry=0x7ffd57a5beb0, isnull=isnull@entry=0x7ffd57a65af0 "\001\001")
Ini dapat direproduksi dan meninggalkan dump inti ~ 9GB.SELECT COUNT(*) from comments;
diizinkanVACUUM comments;
untuk menyelesaikan, trik yang sama tidak berfungsi di tabel lain.SELECT COUNT(*) from photos;
danVACUUM photos;
sekarang mati denganERROR: MultiXactId 302740528 has not been created yet -- apparent wraparound
- yang satu ini menghantui setiap tabel, di mana kesalahan lain tidak muncul lagi.
Pikiran
DB dipalu oleh banyak ( mungkin duplikat ) menulis denganDB sedang melakukanON CONFLICT
klausaVACUUM
ketika kernel panik terjadi, saya percaya itu adalah apa yang tersisa yang menyebabkan masalah dengannonexistent MultiXactIds
daninvisible tuple
- Data dikumpulkan dengan perayap selama rentang 2+ tahun, dan saya benar-benar baik-baik saja dengan kehilangan sebagiannya
- Sekarang saya melakukan backup
- Tidak ada kendala relasional antara tabel atau pemicu
Berikut ini adalah output pg_controldata seperti yang sekarang:
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
Pembaruan
- ( 9 desember 2016 ) Ketika membaca tentang MultiXactIds yang tidak ada , saya ingat bahwa database saya tidak sedang dimuat pada saat crash, tetapi sedang memproses
VACUUM
permintaan manual . Saya telah mengambil webserver dan crawler secara offline setelah saya menyadari bahwa hanya ada 3% ruang yang tersisa di disk. Saya seharusnya memeriksa/var/log
file-file besar, tetapi saya keliru menyalahkan PostgreSQL dan mencobaVACUUM FULL
, hanya untuk menemukannya dibatalkan karena ruang yang tersisa sedikit pada perangkat. Jadi saya sudah memulai VACUUM biasa dan membiarkannya begitu. - ( 14 Desember 2016 ) Mengunduh 9,5 cabang sumber PostgreSQL dari Github, mengomentari blok di heapam.c dan multixact.c dan mengompilasinya dengan harapan tidak akan membuang kesalahan ini. Tetapi server tidak mau memulai, karena harus dikonfigurasi dengan flag yang sama dengan yang saya gunakan di APT. Ada sekitar 47 bendera, masing-masing membutuhkan ketergantungan dengan nama yang tidak jelas, jadi saya menyerah pada ide itu.
( 16 desember 2016 ) Saya telah menemukan cara untuk menghilangkan tupel dengan stempel waktu yang tidak valid dengan mem-posting halaman yang relevan. Saya pertama-tama mengatur opsi berikut di
psql
:\set FETCH_COUNT 1 \pset pager off
Saya kemudian melakukannya
SELECT ctid, * FROM comments;
. Dengan cara itu memuntahkanctid
tuple buruk sebelum permintaan mati. Saya kemudian melanjutkan untuk mengisi halaman itu dengan angka nol:dd if=/dev/zero of=/var/lib/postgresql/9.5/main/base/16385/16443 bs=8K seek=92803 count=1 conv=notrunc
Tetapi setiap halaman, yang dihilangkan dengan cara ini, memecah halaman sebelumnya, menghasilkan halaman yang16442
sekarang memiliki sebuah tuple dengan cap waktu yang tidak valid. Tidak yakin apa yang saya lakukan salah di sini.( 16 desember 2016 ) Mencoba
pg_dump -Fc --table photos vw > photos.bak
menghasilkan kesalahan segmentasi setelah 1.3GB ( dari mungkin 800GB ) tertulis. Berikut adalah log server: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
Berikut ini adalah stacktrace pendek:
#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)
Saya tidak tahu bagaimana cara mengatasinya.
( 29 desember 2016 ) Saya telah menulis sebuah utilitas yang berfungsi
SELECT * FROM tablename LIMIT 10000 OFFSET 0
, menambah offset dan mempersempit tupel yang mati, dan telah berhasil menggandakan data pada mesin lokal saya kecuali tupel ( saya harap satu-satunya ) yang saya korup secara manual. Seharusnya juga menunggu jika server restart. Namun saya tidak memiliki cukup ruang pada RAID saya, dan saya telah membuat tablespaceslowdisk
pada HDD 8TB. Ketika saya berusahaCREATE DATABASE vwslow WITH TABLESPACE slowdisk
, itu tidak akan terjadi dengan kesalahan: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;
Manual
CHECKPOINT
menghasilkan kesalahan yang sama.Restart server membuat kesalahan pos pemeriksaan hilang dan biarkan saya menjalankan alat saya. Akan menjawab pertanyaan saya dan menerbitkan kode jika berfungsi.