错误
尝试删除包含无效时间戳记的元组
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内核崩溃时,我有一个在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
我自然尝试删除有问题的元组,但最终却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被子句的大量(可能重复的)写入重DB在ON CONFLICT
击了VACUUM
发生内核恐慌时正在执行操作,我相信正是它所留下的问题导致了nonexistent MultiXactIds
和invisible 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%的空间后,我使Web服务器和搜寻器脱机。我应该检查/var/log
大文件,但是我错误地责怪PostgreSQL并且尝试了VACUUM FULL
,却发现由于设备上的空间太小而中止了它。因此,我已经开始使用普通的VACUUM并留在那儿了。 - (2016年12月14日)从Github下载了9.5版本的PostgreSQL源代码,注释掉了heapam.c和multixact.c中的块,并对其进行了编译,希望它不会引发这些错误。但是服务器无法启动,因为必须配置与我从APT获得的标志相同的标志。大约有47个标志,每个标志都需要一个名称不明显的依赖项,因此我放弃了这个想法。
(2016年12月16日)我找到了一种方法,通过将相关页面清零来摆脱带有无效时间戳的元组。我首先在中设置以下选项
psql
:\set FETCH_COUNT 1 \pset pager off
然后我做
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
这是一个简短的堆栈跟踪:
#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上没有足够的空间,并且slowdisk
在8TB 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
导致了同样的错误。服务器重新启动使检查点错误消失了,让我运行我的工具。将回答我的问题并发布代码(如果可行)。