Kai*_*Kai 25 postgresql recovery corruption disaster-recovery postgresql-9.5
尝试删除包含无效时间戳的元组
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';
Run Code Online (Sandbox Code Playgroud)
结束于
ERROR: attempted to delete invisible tuple
Run Code Online (Sandbox Code Playgroud)
有一个 2009 年的邮件列表讨论了完全相同的错误消息,OP 修复了它,但我没有找到关于他是如何做到的或可能导致此错误的原因的解释。
由于谷歌搜索量不足以及我对 PostgreSQL 的了解有限,我很无助。
我在 Debian 8 上运行了 PostgreSQL 9.5.5 服务器(~4TB 数据,所有默认设置,内存限制除外),当时操作系统内核崩溃了——可能是在重建 /dev/md1 时交换所在的位置。在此之前,PostgreSQL 用一个 400GB 的日志文件吃光了几乎所有的磁盘空间。操作系统再也没有启动过,磁盘检查没问题,所以我从 LiveCD 启动并将每个块设备备份到映像,以防万一。我已经成功地从 /dev/md2 重建了 / 目录,fsck 显示了一个干净的文件系统,并且我已经将 PGDATA 文件夹备份到了一个外部硬盘上。
在我格式化 md 设备并重新安装操作系统和新的 postgresql-9.5 之后,我停止了 PostgreSQL 服务器,将 PGDATA 文件夹移动并更改为 postgres 用户,然后启动服务器 - 一切似乎都很好,没有错误。
我一开始pg_dumpall,它就死了
Error message from server: ERROR: timestamp out of range
Run Code Online (Sandbox Code Playgroud)
我很自然地尝试删除有问题的元组,结果却invisible tuple一次又一次地出现相同的错误。
首先,由于页面损坏,DELETE 查询失败,因此我设置了以下设置:
zero_damaged_pages = on
ignore_system_indexes = on
enable_indexscan = off
enable_bitmapscan = off
enable_indexonlyscan = off
Run Code Online (Sandbox Code Playgroud)
现在我注意到当我再次运行相同的查询时,服务器一遍又一遍地将相同的页面归零,不知道这意味着什么:
invalid page in block 92800 of relation base/16385/16443; zeroing out page
Run Code Online (Sandbox Code Playgroud)
我试过按照未定义的顺序进行操作:
pg_resetxlog -D $PGDATA 完成了它的工作,没有任何错误或消息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-这一个经常出没的每个表,而其他错误不会弹出了。ON CONFLICT条款VACUUM,当内核恐慌发生,我相信它是什么剩下的部分,是造成麻烦nonexistent MultiXactIds和invisible tuple这是截至目前的 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
Run Code Online (Sandbox Code Playgroud)
VACUUM请求。在我意识到磁盘上只剩下 3% 的空间后,我已将网络服务器和爬虫脱机。我应该检查/var/log大文件,但我错误地归咎于 PostgreSQL 并尝试过VACUUM FULL,却发现它由于设备上剩余的空间很少而中止。所以我已经开始了普通的 VACUUM 并保留了它。(2016 年 12 月 16 日)我找到了一种通过将相关页面归零来摆脱时间戳无效的元组的方法。我首先在以下选项中设置psql:
\set FETCH_COUNT 1
\pset pager off
Run Code Online (Sandbox Code Playgroud)
我接着做SELECT ctid, * FROM comments;。这样它就会ctid在查询结束之前吐出一个错误的元组。然后我继续用零填充该页面:dd if=/dev/zero of=/var/lib/postgresql/9.5/main/base/16385/16443 bs=8K seek=92803 count=1 conv=notrunc但是每个页面,以这种方式归零,打破了前一页,导致页面16442现在有一个带有无效时间戳的元组。不确定我在这里做错了什么。
(2016 年 12 月 16 日)pg_dump -Fc --table photos vw > photos.bak在写入1.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
Run Code Online (Sandbox Code Playgroud)
这是一个简短的堆栈跟踪:
#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)
Run Code Online (Sandbox Code Playgroud)
我不知道如何解决这个问题。
(2016 年 12 月 29 日)我编写了一个实用程序,它可以SELECT * FROM tablename LIMIT 10000 OFFSET 0增加偏移量并缩小死元组周围的范围,并且它已成功复制了我本地机器上的数据,除了我手动损坏的元组(我希望是唯一的)。如果服务器重新启动,它也应该等待。但是我的 RAID 上没有足够的空间,我slowdisk在 8TB 硬盘上创建了一个表空间。当我尝试时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;
Run Code Online (Sandbox Code Playgroud)
手动CHECKPOINT导致相同的错误。
服务器重启使检查点错误消失,让我运行我的工具。如果有效,将回答我的问题并发布代码。
SELECT好吧,我已经成功地自动化了和的恢复过程INSERT INTO,跳过范围并在服务器崩溃时等待。我首先在 Node 中对其进行了编码 - 它从 中提取了未损坏的数据comments,并且仍在继续。
昨天我决定尝试 Golang,这里有一个包含 Go 代码的存储库: https: //github.com/kaivi/pg_ripper我会尽快更新它,这样它就能真正解决坏元组问题,而不仅仅是放弃整体范围包含一个。
| 归档时间: |
|
| 查看次数: |
2652 次 |
| 最近记录: |