standby recovery fails (tablespace related) (tentative patch and discussion)
Paul Guo <pguo@pivotal.io>
From: Paul Guo <pguo@pivotal.io>
To: pgsql-hackers@postgresql.org
Date: 2019-04-17T07:56:30Z
Lists: pgsql-hackers
Attachments
- 0001-Recursively-create-tablespace-directories-if-those-a.patch (application/octet-stream) patch 0001
Hello postgres hackers, Recently my colleagues and I encountered an issue: a standby can not recover after an unclean shutdown and it's related to tablespace. The issue is that the standby re-replay some xlog that needs tablespace directories (e.g. create a database with tablespace), but the tablespace directories has already been removed in the previous replay. In details, the standby normally finishes replaying for the below operations, but due to unclean shutdown, the redo lsn is not updated in pg_control and is still kept a value before the 'create db with tabspace' xlog, however since the tablespace directories were removed so it reports error when repay the database create wal. create db with tablespace drop database drop tablespace. Here is the log on the standby. 2019-04-17 14:52:14.926 CST [23029] LOG: starting PostgreSQL 12devel on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4), 64-bit 2019-04-17 14:52:14.927 CST [23029] LOG: listening on IPv4 address "192.168.35.130", port 5432 2019-04-17 14:52:14.929 CST [23029] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432" 2019-04-17 14:52:14.943 CST [23030] LOG: database system was interrupted while in recovery at log time 2019-04-17 14:48:27 CST 2019-04-17 14:52:14.943 CST [23030] HINT: If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target. 2019-04-17 14:52:14.949 CST [23030] LOG: entering standby mode 2019-04-17 14:52:14.950 CST [23030] LOG: redo starts at 0/30105B8 2019-04-17 14:52:14.951 CST [23030] FATAL: could not create directory "pg_tblspc/65546/PG_12_201904072/65547": No such file or directory 2019-04-17 14:52:14.951 CST [23030] CONTEXT: WAL redo at 0/3011650 for Database/CREATE: copy dir 1663/1 to 65546/65547 2019-04-17 14:52:14.951 CST [23029] LOG: startup process (PID 23030) exited with exit code 1 2019-04-17 14:52:14.951 CST [23029] LOG: terminating any other active server processes 2019-04-17 14:52:14.953 CST [23029] LOG: database system is shut down Steps to reprodce: 1. setup a master and standby. 2. On both side, run: mkdir /tmp/some_isolation2_pg_basebackup_tablespace 3. Run SQLs: drop tablespace if exists some_isolation2_pg_basebackup_tablespace; create tablespace some_isolation2_pg_basebackup_tablespace location '/tmp/some_isolation2_pg_basebackup_tablespace'; 3. Clean shutdown and restart both postgres instances. 4. Run the following SQLs: drop database if exists some_database_with_tablespace; create database some_database_with_tablespace tablespace some_isolation2_pg_basebackup_tablespace; drop database some_database_with_tablespace; drop tablespace some_isolation2_pg_basebackup_tablespace; \! pkill -9 postgres; ssh host70 pkill -9 postgres Note immediate shutdown via pg_ctl should also be able to reproduce and the above steps probably does not 100% reproduce. I created an initial patch for this issue (see the attachment). The idea is re-creating those directories recursively. The above issue exists in dbase_redo(), but TablespaceCreateDbspace (for relation file create redo) is probably buggy also so I modified that function also. Even there is no bug in that function, it seems that using simple pg_mkdir_p() is cleaner. Note reading TablespaceCreateDbspace(), I found it seems that this issue has already be thought though insufficient but frankly this solution (directory recreation) seems to be not perfect given actually this should have been the responsibility of tablespace creation (also tablespace creation does more like symlink creation, etc). Also, I'm not sure whether we need to use invalid page mechanism (see xlogutils.c). Another solution is that, actually, we create a checkpoint when createdb/movedb/dropdb/droptablespace, maybe we should enforce to create restartpoint on standby for such special kind of checkpoint wal - that means we need to set a flag in checkpoing wal and let checkpoint redo code to create restartpoint if that flag is set. This solution seems to be safer. Thanks, Paul
Commits
-
Improve recently-added test reliability
- ad0e08394746 10.22 landed
- 9d5c96d9be64 14.5 landed
- 8c5d9ccca967 13.8 landed
- 782e5631e5dd 12.12 landed
- 772e6383d1da 11.17 landed
- 6c1c9f88ad54 16.0 landed
- 6390bc740f90 15.0 landed
-
Fix new recovery test for log_error_verbosity=verbose case
- b998196bb59a 16.0 cited
-
Fix test instability
- fcd72cf295c3 11.17 landed
- 7cfe688dee86 13.8 landed
- 798d64488ca9 15.0 landed
- 6ffaf75a8001 10.22 landed
- 658e5d53459f 12.12 landed
- 59be1c942a47 16.0 landed
- 4d8d85740c02 14.5 landed
-
Fix replay of create database records on standby
- 9e4f914b5eba 16.0 landed
- a3aacb7cbfc7 14.5 landed
- 9a7e26b9c2ac 13.8 landed
- 8348413dbded 15.0 landed
- 6d20f8c5a46a 12.12 landed
- 5a10c262fc60 11.17 landed
- 084318c33a1f 10.22 landed
- ffd28516e699 14.3 landed
- 50e3ed8e9172 13.7 landed
- 49d9cfc68bf4 15.0 landed
-
Allow "in place" tablespaces.
- 961cab0a5a90 14.5 landed
- 16e7a8fd8e97 13.8 landed
- ca347f5433ed 12.12 landed
- 7bdbbb87340f 10.22 landed
- 258c896418bf 11.17 landed
-
Fix get_dirent_type() for Windows junction points.
- fee0165fc1cf 14.5 landed
- 6d306ab73168 15.0 landed
- 9d3444dcce4d 16.0 landed
-
Revert "Fix replay of create database records on standby"
- bf902c13930c 15.0 landed
- adc943b4e1fe 14.3 landed
- a54ed2de80ec 13.7 landed
-
Add end-to-end testing of pg_basebackup's tar-format output.
- 081876d75ea1 14.0 cited
-
Make DROP DATABASE command generate less WAL records.
- e6d8069522c8 13.0 cited
-
Consolidate methods for translating a Perl path to a Windows path.
- 660a2b19038b 12.0 cited