Re: replay of CREATE TABLESPACE eats data at wal_level=minimal
Noah Misch <noah@leadboat.com>
From: Noah Misch <noah@leadboat.com>
To: Robert Haas <robertmhaas@gmail.com>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2021-08-10T01:23:07Z
Lists: pgsql-hackers
Attachments
- XLOG_TBLSPC_CREATE-minimal-v0.patch (text/plain) patch v0
On Mon, Aug 09, 2021 at 01:08:42PM -0400, Robert Haas wrote: > To reproduce, initialize a cluster with wal_level=minimal and > max_wal_senders=0. Then from psql: > > \! mkdir /tmp/goose > > CHECKPOINT; > CREATE TABLESPACE goose LOCATION '/tmp/goose'; > SET wal_skip_threshold=0; > BEGIN; > CREATE TABLE wild (a int, b text) TABLESPACE goose; > INSERT INTO wild VALUES (1, 'chase'); > COMMIT; > SELECT * FROM wild; > > As expected, you will see one row in table 'wild'. Now perform an > immediate shutdown. Restart the server. Table 'wild' is now empty. Thanks for finding the problem. It's a bad problem. > The problem appears to be that tblspc_redo() calls > create_tablespace_directories(), which says: > > /* > * Our theory for replaying a CREATE is to forcibly drop the target > * subdirectory if present, and then recreate it. This may be more > * work than needed, but it is simple to implement. > */ > > Unfortunately, this theory (which dates to > c86f467d18aa58e18fd85b560b46d8de014e6017, vintage 2010, by Bruce) is > correct only with wal_level>minimal. At wal_level='minimal', we can > replay the record to recreate the relfilenode, but not the records > that would have created the contents. However, note that if the table > is smaller than wal_skip_threshold, then we'll log full-page images of > the contents at commit time even at wal_level='minimal' after which we > have no problem. As far as I can see, this bug has "always" existed, > but before c6b92041d38512a4176ed76ad06f713d2e6c01a8 (2020, Noah) you > would have needed a different test case. Specifically, you would have > needed to use COPY to put the row in the table, and you would have > needed to omit setting wal_skip_threshold since it didn't exist yet. Agreed. > I don't presently have a specific idea about how to fix this. Can't recovery just not delete the directory, create it if doesn't exist, and be happy if it does exist? Like the attached WIP. If we think it's possible for a crash during mkdir to leave a directory having the wrong permissions, adding a chmod would be in order.
Commits
-
Fix data loss in wal_level=minimal crash recovery of CREATE TABLESPACE.
- 978998dbde2a 9.6.24 landed
- f11c1bb17099 10.19 landed
- 6ebd2426bda2 11.14 landed
- a494f1023264 12.9 landed
- b18669f5e652 13.5 landed
- 5513c09c8999 14.0 landed
- 97ddda8a82ac 15.0 landed
-
Skip WAL for new relfilenodes, under wal_level=minimal.
- c6b92041d385 13.0 cited
-
Properly replay CREATE TABLESPACE during crash recovery by deleting
- c86f467d18aa 9.1.0 cited