Re: [HACKERS] WAL logging problem in 9.4.3?
Noah Misch <noah@leadboat.com>
On Tue, Jan 14, 2020 at 07:35:22PM +0900, Kyotaro Horiguchi wrote:
> At Thu, 26 Dec 2019 12:46:39 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in
> > At Wed, 25 Dec 2019 16:15:21 -0800, Noah Misch <noah@leadboat.com> wrote in
> > > === Defect 1: Forgets to skip WAL after SAVEPOINT; DROP TABLE; ROLLBACK TO
> > >
> > > A test in transactions.sql now fails in AssertPendingSyncs_RelationCache(),
> > > when running "make check" under wal_level=minimal. I test this way:
> > >
> > > printf '%s\n%s\n' 'wal_level = minimal' 'max_wal_senders = 0' >$PWD/minimal.conf
> > > make check TEMP_CONFIG=$PWD/minimal.conf
> > >
> > > Self-contained demonstration:
> > > begin;
> > > create table t (c int);
> > > savepoint q; drop table t; rollback to q; -- forgets table is skipping wal
> > > commit; -- assertion failure
>
> This is complex than expected. The DROP TABLE unconditionally removed
> relcache entry. To fix that, I tried to use rd_isinvalid but it failed
> because there's a state that a relcache invalid but the corresponding
> catalog entry is alive.
>
> In the attached patch 0002, I added a boolean in relcache that
> indicates that the relation is already removed in catalog but not
> committed.
This design could work, but some if its properties aren't ideal. For example,
RelationIdGetRelation() can return a !rd_isvalid relation when the relation
has been dropped. What others designs did you consider, if any?
On Thu, Jan 16, 2020 at 02:20:57PM +0900, Kyotaro Horiguchi wrote:
> --- a/src/backend/utils/cache/relcache.c
> +++ b/src/backend/utils/cache/relcache.c
> @@ -3114,8 +3153,10 @@ AtEOXact_cleanup(Relation relation, bool isCommit)
> */
> if (relation->rd_createSubid != InvalidSubTransactionId)
> {
> - if (isCommit)
> - relation->rd_createSubid = InvalidSubTransactionId;
> + relation->rd_createSubid = InvalidSubTransactionId;
> +
> + if (isCommit && !relation->rd_isdropped)
> + {} /* Nothing to do */
What is the purpose of this particular change? This executes at the end of a
top-level transaction. We've already done any necessary syncing, and we're
clearing any flags that caused WAL skipping. I think it's no longer
productive to treat dropped relations differently.
> @@ -3232,6 +3272,19 @@ AtEOSubXact_cleanup(Relation relation, bool isCommit,
> }
> }
>
> + /*
> + * If this relation registered pending sync then dropped, subxact rollback
> + * cancels the uncommitted drop, and commit propagates it to the parent.
> + */
> + if (relation->rd_isdropped)
> + {
> + Assert (!relation->rd_isvalid &&
> + (relation->rd_createSubid != InvalidSubTransactionId ||
> + relation->rd_firstRelfilenodeSubid != InvalidSubTransactionId));
> + if (!isCommit)
> + relation->rd_isdropped = false;
This does the wrong thing when there exists some subtransaction rollback that
does not rollback the DROP:
\pset null 'NULL'
begin;
create extension pg_visibility;
create table droppedtest (c int);
select 'droppedtest'::regclass::oid as oid \gset
savepoint q; drop table droppedtest; release q; -- rd_dropped==true
select * from pg_visibility_map(:oid); -- processes !rd_isvalid rel (not ideal)
savepoint q; select 1; rollback to q; -- rd_dropped==false (wrong)
savepoint q; select 1; rollback to q;
select pg_relation_size(:oid), pg_relation_filepath(:oid),
has_table_privilege(:oid, 'SELECT'); -- all nulls, okay
select * from pg_visibility_map(:oid); -- assertion failure
rollback;
Commits
-
Add perl2host call missing from a new test file.
- 70de4e950c3b 13.0 landed
-
Skip WAL for new relfilenodes, under wal_level=minimal.
- c6b92041d385 13.0 landed
- 9db4b9da2801 9.5.22 landed
- a653bd8aa76e 9.6.18 landed
- 9d6215205e5a 10.13 landed
- 03b89f1949a9 11.8 landed
- e4b0a02ef8c8 12.3 landed
- cb2fd7eac285 13.0 landed
-
Revert "Skip WAL for new relfilenodes, under wal_level=minimal."
- b31e96ba420f 9.5.22 landed
- 348f15e22e94 9.6.18 landed
- 0a6c9c66da26 10.13 landed
- 63631ee64f84 12.3 landed
- 2fbdebc248ec 11.8 landed
- de9396326edc 13.0 landed
-
Back-patch log_newpage_range().
- e0dd086414f7 9.5.22 landed
- 14d2bb4941e6 9.6.18 landed
- 43434ed94d80 10.13 landed
- ae86e46c3b7b 11.8 landed
-
During heap rebuild, lock any TOAST index until end of transaction.
- a8f754aea014 9.6.18 landed
- 978da2a95597 9.5.22 landed
- 78a34c68920a 10.13 landed
- 88b3a6cd2623 12.3 landed
- 4433c6e8c0a5 11.8 landed
- e629a01f6973 13.0 landed
-
In log_newpage_range(), heed forkNum and page_std arguments.
- a5abec521c5d 12.3 landed
- d3e572855be1 13.0 landed
-
Back-patch src/test/recovery and PostgresNode from 9.6 to 9.5.
- 12034da6cc39 9.5.22 landed
-
Reduce pg_ctl's reaction time when waiting for postmaster start/stop.
- c61559ec3a41 10.0 cited
-
Accelerate end-of-transaction dropping of relations
- 279628a0a7cf 9.3.0 cited
-
Redesign the planner's handling of index-descent cost estimation.
- 31f38f28b00c 9.3.0 cited
-
Make TRUNCATE do truncate-in-place when processing a relation that was created
- cab9a0656c36 9.0.0 cited