PostgreSQL XÓA TỪ thất bại với `Error: đã cố xóa tuple`


25

Lỗi

Đang cố gắng xóa các bộ dữ liệu có dấu thời gian không hợp lệ bằng

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

kết thúc ở

ERROR:  attempted to delete invisible tuple

một danh sách gửi thư từ năm 2009 thảo luận về cùng một thông báo lỗi, trong đó OP đã sửa nó, nhưng tôi không tìm thấy lời giải thích nào về cách anh ấy đã làm nó hoặc điều gì có thể dẫn đến lỗi này.

Tôi bất lực vì thiếu lượt truy cập trên Google và kiến ​​thức hạn chế của tôi về PostgreSQL.

Điều gì dẫn đến tham nhũng

Tôi đã có máy chủ PostgreSQL 9.5.5 ( ~ 4TB dữ liệu, tất cả các cài đặt mặc định, ngoại trừ giới hạn bộ nhớ đã tăng ) chạy trên Debian 8, khi nhân hệ điều hành hoảng loạn - có thể trong khi xây dựng lại / dev / md1 nơi đặt trao đổi. Trước đó, PostgreSQL đã ăn gần hết dung lượng đĩa với tệp nhật ký 400GB. Hệ điều hành không bao giờ khởi động lại, kiểm tra đĩa đều ổn, vì vậy tôi đã khởi động từ LiveCD và sao lưu từng thiết bị khối vào hình ảnh, chỉ trong trường hợp. Tôi đã xây dựng lại thành công / thư mục từ / dev / md2, fsck hiển thị một hệ thống tệp sạch và tôi đã sao lưu thư mục PGDATA vào ổ cứng ngoài.

Tôi đã làm gì để cố gắng phục hồi

Sau khi tôi định dạng các thiết bị md và cài đặt lại HĐH cùng với postgresql-9.5 mới, tôi đã dừng máy chủ PostgreQuery, di chuyển và truy cập thư mục PGDATA cho người dùng postgres và khởi động máy chủ - mọi thứ đều ổn, không có lỗi.

Ngay khi tôi bắt đầu pg_dumpall, nó đã chết với

Error message from server: ERROR:  timestamp out of range

Tôi đã cố gắng tự nhiên để xóa các bộ vi phạm, chỉ để kết thúc với cùng một invisible tuplelỗi lặp đi lặp lại.

Những điều tôi đã thử

Trước hết, XÓA các truy vấn không thành công do các trang bị hỏng, vì vậy tôi đã đặt các cài đặt sau:

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

Bây giờ tôi nhận thấy rằng khi tôi chạy lại các truy vấn tương tự, máy chủ sẽ lặp đi lặp lại các trang giống nhau, không chắc nó có nghĩa là gì:

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

Tôi đã thử làm theo thứ tự không xác định:

  • pg_resetxlog -D $PGDATA đã làm công việc của mình mà không có bất kỳ lỗi hoặc tin nhắn
  • Đã xóa tất cả các chỉ mục bao gồm các ràng buộc pkey
  • CREATE TABLE aaa AS (SELECT * FROM comments);dẫn đến Segmentation faulttrên

    heap_deform_tuple (tuple=tuple@entry=0x7f0d1be29b08, tupleDesc=tupleDesc@entry=0x7f0d1a35abe0, values=values@entry=0x7ffd57a5beb0, isnull=isnull@entry=0x7ffd57a65af0 "\001\001") Nó có thể tái tạo và để lại một bãi chứa lõi ~ 9GB.

  • SELECT COUNT(*) from comments;được phép VACUUM comments;hoàn thành, cùng một thủ thuật không hoạt động trên các bảng khác.
  • SELECT COUNT(*) from photos;VACUUM photos;bây giờ chết với ERROR: MultiXactId 302740528 has not been created yet -- apparent wraparound- điều này ám ảnh mọi bảng, nơi các lỗi khác không xuất hiện nữa.

Suy nghĩ

  • DB đã bị cản trở bởi rất nhiều ( có thể trùng lặp ) với ON CONFLICTmệnh đề DB đang thực hiện VACUUMkhi sự hoảng loạn hạt nhân xảy ra, tôi tin rằng đó là những gì còn lại của nó gây rắc rối với nonexistent MultiXactIdsinvisible tuple
  • Dữ liệu được thu thập với trình thu thập thông tin trong hơn 2 năm và tôi hoàn toàn ổn khi mất một phần dữ liệu
  • Bây giờ tôi làm bản sao lưu
  • Không có ràng buộc quan hệ giữa các bảng và bất kỳ trình kích hoạt nào

Đây là đầu ra pg_controldata tính đến thời điểm hiện tại:

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

Cập nhật

  • ( 9 tháng 12 năm 2016 ) Trong khi đọc về MultiXactIds không tồn tại , tôi đã nhớ rằng cơ sở dữ liệu của tôi không tải hoạt động tại thời điểm xảy ra sự cố, nhưng nó đang xử lý một VACUUMyêu cầu thủ công. Tôi đã đưa trình duyệt web và trình thu thập dữ liệu ngoại tuyến sau khi tôi nhận ra rằng chỉ còn 3% dung lượng trên đĩa. Tôi nên kiểm tra /var/logcác tệp lớn, nhưng tôi đã nhầm lẫn PostgreSQL và đã thử VACUUM FULL, chỉ để thấy nó bị hủy bỏ do không còn chỗ trống trên thiết bị. Vì vậy, tôi đã bắt đầu VACUUM thông thường và để nó ở đó.
  • ( 14 tháng 12 năm 2016 ) Đã tải xuống một nhánh 9,5 nguồn PostgreSQL từ Github, nhận xét các khối trong heapam.cmultixact.c và biên dịch nó với hy vọng rằng nó sẽ không ném các lỗi này. Nhưng máy chủ sẽ không khởi động, vì nó phải được cấu hình với cùng các cờ được sử dụng trong một cái tôi có từ APT. Có khoảng 47 lá cờ, mỗi lá cờ đòi hỏi một sự phụ thuộc với tên không rõ ràng, vì vậy tôi đã từ bỏ ý tưởng đó.
  • ( 16 tháng 12 năm 2016 ) Tôi đã tìm ra cách để loại bỏ các bộ dữ liệu có dấu thời gian không hợp lệ bằng cách xóa các trang có liên quan. Trước tiên tôi đặt các tùy chọn sau trong psql:

    \set FETCH_COUNT 1
    \pset pager off
    

    Sau đó tôi làm SELECT ctid, * FROM comments;. Bằng cách đó, nó tạo ra ctidmột tuple xấu trước khi truy vấn chết. Sau đó, tôi tiến hành điền vào trang đó bằng các số không: dd if=/dev/zero of=/var/lib/postgresql/9.5/main/base/16385/16443 bs=8K seek=92803 count=1 conv=notruncNhưng mỗi trang, bỏ qua cách này, phá vỡ trang trước đó, dẫn đến trang 16442hiện có một tuple với dấu thời gian không hợp lệ. Không chắc chắn những gì tôi đang làm sai ở đây.

  • ( 16 tháng 12 năm 2016 ) Cố gắng pg_dump -Fc --table photos vw > photos.bakdẫn đến lỗi phân đoạn sau khi viết 1,3 GB ( trong số có thể là 800 GB ). Đây là nhật ký máy chủ:

    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
    

    Đây là một stacktrace ngắn:

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

    Tôi không có ý tưởng làm thế nào để làm việc xung quanh đó.

  • ( 29 tháng 12 năm 2016 ) tôi đã viết một tiện ích mà làm SELECT * FROM tablename LIMIT 10000 OFFSET 0, incrementing bù đắp và thu hẹp các bộ xung quanh chết, và nó đã lặp lại thành công dữ liệu trên máy tính địa phương của tôi, ngoại trừ các tuple ( Tôi hy vọng những người duy nhất ) Tôi đã tự hỏng. Nó cũng được cho là chờ nếu máy chủ khởi động lại. Tuy nhiên, tôi không còn đủ dung lượng trên RAID và tôi đã tạo một vùng bảng slowdisktrên ổ cứng 8TB. Khi tôi cố gắng CREATE DATABASE vwslow WITH TABLESPACE slowdisk, nó sẽ không làm như vậy với lỗi:

    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;
    

    Hướng dẫn sử dụng CHECKPOINTdẫn đến các lỗi tương tự.

    Khởi động lại máy chủ đã làm cho lỗi điểm kiểm tra biến mất và để tôi chạy công cụ của mình. Sẽ trả lời câu hỏi của tôi và xuất bản mã nếu nó hoạt động.


Đọc cái này và hành động trước khi thử làm bất cứ điều gì khác: wiki.postgresql.org/wiki/Corruption . Mặc dù có vẻ như hơi muộn. Tôi rất nghi ngờ vấn đề đĩa / xây dựng lại RAID là nguyên nhân gốc rễ ở đây.
Craig Ringer

Bạn đã giữ một bản sao của thư mục dữ liệu từ trước khi bạn thực hiện resetxlog, v.v.?
Craig Ringer

Không phải là datadir, nhưng tôi đã di chuyển hình ảnh đĩa thô bên ngoài nơi chúng an toàn hơn. Chúng vẫn ổn, vì tôi đã xây dựng lại RAID của mình từ chúng.
Kai

1
@CraigRinger bạn sẽ viết câu trả lời về điều này? Có lẽ bạn là một trong số ít người dùng trả lời trong thẻ Postgres và có thể nói điều gì đó hữu ích về vấn đề này. Có vẻ như rất ít có thể được thực hiện.
ypercubeᵀᴹ

4
Bạn sẽ không tìm thấy câu trả lời về điều này. Erwin có thể giúp bạn. Rụt rè về điều đó, hãy tìm David Fetter, hoặc AndrewSW / RhodiumToad trên irc.freenode.net/#postgresql. Hãy cho chúng tôi (dba.se) những gì họ tìm thấy. Tôi có cảm giác đây sẽ là một công việc tư vấn được trả tiền sẽ yêu cầu toàn quyền truy cập vào cơ sở dữ liệu của bạn. developer.postgresql.org/~adunstan Linkedin.com/in/davidfetter Tôi không có liên kết với một trong hai người đó, hoặc công ty của họ. Nhưng, họ là những người duy nhất mà cá nhân tôi tin tưởng để thoát khỏi sự khó khăn đó.
Evan Carroll

Câu trả lời:


2

Chà, tôi đã quản lý để tự động hóa quá trình khôi phục SELECTINSERT INTO, bỏ qua các phạm vi và chờ đợi nếu máy chủ gặp sự cố. Lần đầu tiên tôi đã mã hóa nó trong Node - nó đã xé dữ liệu không bị hư hại từ đó commentsvà vẫn đang tiếp tục.

Hôm qua tôi đã quyết định dùng thử Golang và đây là một repo với mã Go: https://github.com/kaivi/pg_ripper Tôi sẽ cập nhật nó sớm để nó thực sự hoạt động xung quanh các bộ dữ liệu xấu và không chỉ từ bỏ toàn bộ phạm vi chứa một.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.