Re: Review for GetWALAvailability() - Mailing list pgsql-hackers
| From | Kyotaro Horiguchi |
|---|---|
| Subject | Re: Review for GetWALAvailability() |
| Date | |
| Msg-id | 20200617.100121.2112248049559508701.horikyota.ntt@gmail.com Whole thread Raw |
| In response to | Re: Review for GetWALAvailability() (Fujii Masao <masao.fujii@oss.nttdata.com>) |
| List | pgsql-hackers |
At Wed, 17 Jun 2020 00:46:38 +0900, Fujii Masao <masao.fujii@oss.nttdata.com> wrote in
> >> 2. InvalidateObsoleteReplicationSlots() uses the loop to scan
> >> replication
> >> slots array and uses the "for" loop in each scan. Also it calls
> >> ReplicationSlotAcquire() for each "for" loop cycle, and
> >> ReplicationSlotAcquire() uses another loop to scan replication slots
> >> array. I don't think this is good design.
> >>
> >> ISTM that we can get rid of ReplicationSlotAcquire()'s loop because
> >> InvalidateObsoleteReplicationSlots() already know the index of the
> >> slot
> >> that we want to find. The attached patch does that. Thought?
> > The inner loop is expected to run at most several times per
> > checkpoint, which won't be a serious problem. However, it is better if
> > we can get rid of that in a reasonable way.
> > The attached patch changes the behavior for SAB_Block. Before the
> > patch, it rescans from the first slot for the same name, but with the
> > patch it just rechecks the same slot. The only caller of the function
> > with SAB_Block is ReplicationSlotDrop and I don't come up with a case
> > where another slot with the same name is created at different place
> > before the condition variable fires. But I'm not sure the change is
> > completely safe.
>
> Yes, that change might not be safe. So I'm thinking another approach
> to
> fix the issues.
>
> > Maybe some assertion is needed?
> >
> >> 3. There is a corner case where the termination of walsender cleans up
> >> the temporary replication slot while
> >> InvalidateObsoleteReplicationSlots()
> >> is sleeping on ConditionVariableTimedSleep(). In this case,
> >> ReplicationSlotAcquire() is called in the subsequent cycle of the
> >> "for"
> >> loop, cannot find the slot and then emits ERROR message. This leads
> >> to the failure of checkpoint by the checkpointer.
> > Agreed.
> >
> >> To avoid this case, if SAB_Inquire is specified,
> >> ReplicationSlotAcquire()
> >> should return the special value instead of emitting ERROR even when
> >> it cannot find the slot. Also InvalidateObsoleteReplicationSlots()
> >> should
> >> handle that special returned value.
> > I thought the same thing hearing that.
>
> While reading InvalidateObsoleteReplicationSlots() code, I found
> another issue.
>
> ereport(LOG,
> (errmsg("terminating walsender %d
> because replication slot \"%s\" is too
> far behind",
> wspid,
> NameStr(slotname))));
> (void) kill(wspid, SIGTERM);
>
> wspid indicates the PID of process using the slot. That process can be
> a backend, for example, executing pg_replication_slot_advance().
> So "walsender" in the above log message is not always correct.
Agreed.
>
> int wspid = ReplicationSlotAcquire(NameStr(slotname),
> SAB_Inquire);
>
> Why do we need to call ReplicationSlotAcquire() here and mark the slot
> as
> used by the checkpointer? Isn't it enough to check directly the slot's
> active_pid, instead?
> Maybe ReplicationSlotAcquire() is necessary because
> ReplicationSlotRelease() is called later? If so, why do we need to
> call
> ReplicationSlotRelease()? ISTM that we don't need to do that if the
> slot's
> active_pid is zero. No?
My understanding of the reason is that we update a slot value here.
The restriction allows the owner of a slot to assume that all the slot
values don't voluntarily change.
slot.h:104
| * - Individual fields are protected by mutex where only the backend owning
| * the slot is authorized to update the fields from its own slot. The
| * backend owning the slot does not need to take this lock when reading its
| * own fields, while concurrent backends not owning this slot should take the
| * lock when reading this slot's data.
> If my understanding is right, I'd like to propose the attached patch.
> It introduces DeactivateReplicationSlot() and replace the "for" loop
> in InvalidateObsoleteReplicationSlots() with
> it. ReplicationSlotAcquire()
> and ReplicationSlotRelease() are no longer called there.
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
pgsql-hackers by date: