PostgreSQL DELETE FROM `ile başarısız oluyor: Hata: görünmez tuple silmeye kalkıldı`


25

Hata

Geçersiz zaman damgası içeren tupleri silmeye çalışıyor

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';

biter

ERROR:  attempted to delete invisible tuple

2009'dan itibaren OP'nin düzeltdiği aynı hata mesajını tartışan bir posta listesi var , ama nasıl yaptığı veya bu hataya neyin yol açabileceği hakkında bir açıklama bulamıyorum.

Google’da isabet olmamasından ve sınırlı PostgreSQL bilgimden dolayı çaresizim.

Yolsuzluğa ne yol açtı?

İşletim sistemi çekirdeği paniklendiğinde Debian 8'de çalışan bir PostgreSQL 9.5.5 sunucusuna ( ~ 4TB veri, tüm varsayılan ayarlar), büyük olasılıkla takasın bulunduğu yerde / dev / md1 yeniden oluşturulurken debian 8 kullandım. Bundan önce, PostgreSQL neredeyse tüm disk alanını 400GB'lık bir log dosyası ile yedi. İşletim sistemi bir daha önyükleme yapmadı, disk denetimleri tamam oldu, bu yüzden bir LiveCD'den önyükleme yaptım ve her durumda bir blok aygıtını görüntülere yedekledim. / Dev / md2 dizininden / dizinini başarıyla yeniden kurdum, fsck temiz bir dosya sistemi gösterdi ve PGDATA klasörünü harici bir HDD'ye yedekledim.

Kurtarma girişiminde bulunmak için ne yaptım

Md aygıtlarını biçimlendirdikten ve işletim sistemini yeni bir postgresql-9.5 ile birlikte yeniden kurduktan sonra, PostgreSQL sunucusunu durdurdum, PGDATA klasörünü taşındı ve kullanıcıya postgres kullanıcısı olarak hazırladım ve sunucuyu başlattım - her şey yolunda görünüyordu, hiçbir hata yoktu.

Ben başlar başlamaz pg_dumpall, öldü

Error message from server: ERROR:  timestamp out of range

Doğal olarak rahatsız edici tuples'leri silmeye çalıştım, sadece invisible tupletekrar tekrar aynı hatayı bulabilirim.

Denediğim şeyler

Öncelikle, DELETE sorguları bozuk sayfalar nedeniyle başarısız oldu, bu yüzden aşağıdaki ayarları belirledim:

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

Şimdi, aynı sorguları tekrar çalıştırdığımda, sunucunun ne anlama geldiğinden emin olmadan aynı sayfaları tekrar tekrar sıfırladığını fark ettim:

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

Tanımlanamayan bir sıra ile izlemeye çalıştım:

  • pg_resetxlog -D $PGDATA işini herhangi bir hata veya mesaj olmadan yaptı
  • Pkey kısıtlamaları dahil tüm dizinleri silindi
  • CREATE TABLE aaa AS (SELECT * FROM comments);kurşunları Segmentation faultüzerine

    heap_deform_tuple (tuple=tuple@entry=0x7f0d1be29b08, tupleDesc=tupleDesc@entry=0x7f0d1a35abe0, values=values@entry=0x7ffd57a5beb0, isnull=isnull@entry=0x7ffd57a65af0 "\001\001") Tekrar üretilebilir ve ~ 9GB'lık bir çekirdek dökümü bırakır.

  • SELECT COUNT(*) from comments;VACUUM comments;Tamamlanmasına izin verilir , aynı numara başka masalarda da işe yaramaz.
  • SELECT COUNT(*) from photos;ve VACUUM photos;şimdi ölür ERROR: MultiXactId 302740528 has not been created yet -- apparent wraparound- bu, diğer hataların artık ortaya çıkmadığı her masayı ziyaret eder.

Düşünceler

  • DB çok sayıda ( muhtemelen çift ) dövülmüş , ON CONFLICTfıkra ile birlikte yazılmıştır. DB VACUUMpanik ortaya çıktığında bir şeyler yapıyordu , sorun çıkmasına neden olan şeyin ne olduğuna inanıyorum nonexistent MultiXactIdsveinvisible tuple
  • Veriler 2 + yıllık bir süre boyunca tarayıcı ile toplandı ve bazılarını kaybetmek konusunda tamamen iyiyim
  • Şimdi yedeklerim
  • Tablolar arasında ne tetikleyiciler arasında ilişkisel bir kısıtlama yoktu.

Şu andan itibaren pg_controldata çıktısı:

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

Güncellemeler

  • ( 9 Aralık 2016 ) Varolmayan MultiXactIds'leri okurken , veritabanımın çökme anında operasyonel yük altında olmadığını, ancak manuel bir VACUUMistek işlediğini hatırladım . Disklerde yalnızca% 3 yer kaldığını fark ettikten sonra web sunucularını ve tarayıcıları çevrimdışı duruma getirdim. /var/logBüyük dosyaları kontrol etmeliydim , ancak yanlışlıkla PostgreSQL'i suçladım ve VACUUM FULLyalnızca cihazda çok az yer kalması nedeniyle iptal edildiğini bulmak için denedim . Böylece sıradan VAKUM'a başladım ve buna bıraktım.
  • ( 14 Aralık 2016 ) Github’dan 9,5 PostgreSQL kaynak dalı indirdi , heapam.c ve multixact.c içindeki blokları yorumladı ve bu hataları atmayacağını ümit ederek derledi. Ancak sunucu başlamazdı, çünkü APT’de kullandığımla aynı bayraklarla yapılandırılmalıydı. Her biri açık olmayan bir isimle bağımlılık gerektiren yaklaşık 47 bayrak vardı, bu yüzden bu fikirden vazgeçtim.
  • ( 16 aralık 2016 ) Alakalı sayfaları sıfırlayarak geçersiz zaman damgası olan tüfeklerden kurtulmanın bir yolunu buldum. İlk önce aşağıdaki seçenekleri ayarladım psql:

    \set FETCH_COUNT 1
    \pset pager off

    Öyleyse yaparım SELECT ctid, * FROM comments;. Bu şekilde ctid, sorgu sona ermeden önce kötü bir demet tükürür . Daha sonra bu sayfayı sıfırlarla doldurmaya devam ediyorum: dd if=/dev/zero of=/var/lib/postgresql/9.5/main/base/16385/16443 bs=8K seek=92803 count=1 conv=notruncAncak, bu şekilde sıfırlanan her sayfa önceki sayfayı kırar ve sayfa 16442artık geçersiz zaman damgası olan bir demetle sonuçlanır . Neyi yanlış yaptığımdan emin değilim.

  • ( 16 Aralık 2016 ) pg_dump -Fc --table photos vw > photos.bak1.3GB ( muhtemelen 800 GB’den ) yazıldıktan sonra segmentasyon hatasıyla sonuçlanmaya çalışılıyor . İşte sunucu günlüğü:

    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

    İşte kısa bir istif:

    #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)

    Nasıl çalışılacağı hakkında hiçbir fikrim yok.

  • ( 29 Aralık 2016 ) SELECT * FROM tablename LIMIT 10000 OFFSET 0Ölü tupler etrafındaki ofseti artıran ve daraltıcı kılan bir yardımcı program yazdım ve yerel makinemdeki tupler dışındaki verileri başarıyla kopyaladı ( sadece inşallah ) El ile bozdum. Sunucunun yeniden başlatılıp başlatılmayacağı da beklenmelidir. Ancak slowdiskRAID'imde yeterli alan kalmadı ve bir 8TB HDD'de bir tablo alanı oluşturdum . Denemeye başladığımda CREATE DATABASE vwslow WITH TABLESPACE slowdisk, bunu hatalarla yapmayacak:

    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;

    Manuel CHECKPOINTaynı hatalarla sonuçlandı.

    Bir sunucu yeniden başlatıldığında denetim noktası hatası ortadan kalktı ve aracımı çalıştırmama izin verildi. Soruma cevap verecek ve eğer çalışırsa kodu yayınlayacağım.


Başka bir şey yapmayı denemeden önce bunu okuyun ve üzerinde çalışın : wiki.postgresql.org/wiki/Corruption . Biraz geç olmuş gibi görünse de. Buradaki temel sebep olarak disk sorunlarından / RAID yeniden yapılanmasından şüpheliyim.
Craig Ringer,

Resetxlog etc işleminden önce veri dizininin bir kopyasını sakladınız mı?
Craig Ringer,

Datadir'in kendisi değil, ancak ham disk görüntülerini daha güvenli oldukları yer dışına taşıdım. İyiler, çünkü RAID'imi onlardan yeniden oluşturdum.
Kai

1
@CraigRinger bu konuda bir cevap yazar mısın? Muhtemelen Postgres etiketinde cevap veren ve bu konuda faydalı bir şeyler söyleyebilecek az sayıdaki kişiden birisiniz. Çok az şey yapılabilir gibi görünüyor.
ypercubeᵀᴹ

4
Bunun cevabını bulamayacaksın. Erwin size yardım edebilir. Utangaç, David Fetter veya AndrewSW / RhodiumToad için irc.freenode.net/#postgresql adresini arayın. Bize (dba.se) ne bulduğunu söyle. Bunun veri tabanınıza tam erişim gerektiren ücretli bir danışmanlık işi olacağı kanısındayım. developer.postgresql.org/~adunstan linkedin.com/in/davidfetter Bu adamlarla ya da şirketleri ile hiçbir bağlantım yok. Ancak, kişisel olarak bu engelden kurtulmak için güvenebileceğim tek kişi onlar.
Evan Carroll,

Yanıtlar:


2

Şey, kurtarma işlemini otomatik hale getirmeyi SELECTve INSERT INTOaralıkları atlamayı ve sunucu çökerse beklemeyi başarmayı başardım . İlk önce Düğümde kodladım - zarar görmemiş verileri kopardı commentsve hala devam ediyor.

Dün Golang'ı denemeye karar verdim, ve işte Go kodunu içeren bir repo: https://github.com/kaivi/pg_ripper Yakında güncelleyeceğim, böylece gerçekten kötü tuples etrafında işe yarıyor, sadece bütünden vazgeçmiyor birini içeren aralık.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.