Обсуждение: isolation tester limitation in case of multiple injection points in a single command

Поиск
Список
Период
Сортировка

isolation tester limitation in case of multiple injection points in a single command

От
Mihail Nikalayeu
Дата:
Hello, everyone!

While stabilizing tests for [0] I realized I have no idea how to set
up a pretty simple scenario using an isolation tester.

It looks like this:
* session S1 start long running query (CREATE INDEX CONCURRENTLY) and
traps into injection point X
* session S2 executes some command
* session S2 wakes up S1
* now S2 needs to run one more command BUT only AFTER S1 traps into
another injection point Y (and it is still the same CREATE INDEX)
<------- tricky part here

My first idea was to add one more injection point Z with 'notice' type
before Y (not a bulletproof way, but okay for now) - and use some
S2_noop (S1 notices 1) step....
But AFAIU injection_point's 'notice' is a totally different type of notice
compared to RAISE NOTICE - so, isolation_tester just ignores it.

Second idea is to implement some polling procedure to find S1 waiting
in pg_stat_activity... But that feels weird for a spec test. Maybe we
should implement some injection_point_await utility? 

So, my proposal options:
a) tell me if there's a clear solution I missed
b) for 'wait' injection_point - learn isolation tester to detect it
and implement logic like 'S2_query(S1 traps Y)'
c) learn isolation tester to treat 'notice' from injection_point the
same way as RAISE NOTICE + (preferable) add possibility to
apply 'notice' and 'wait' for the same injection point (like
'wait+notice')
d) add injection_point_await - utility to wait until injected point is not "waited" by some backend 

What do you think? Any other ideas?

Best regards,
Mikhail.

[0]: https://commitfest.postgresql.org/patch/5160/

Re: isolation tester limitation in case of multiple injection points in a single command

От
Michael Paquier
Дата:
On Sun, Oct 19, 2025 at 03:41:00PM +0200, Mihail Nikalayeu wrote:
> Hello, everyone!
>
> While stabilizing tests for [0] I realized I have no idea how to set
> up a pretty simple scenario using an isolation tester.
>
> It looks like this:
> * session S1 start long running query (CREATE INDEX CONCURRENTLY) and
> traps into injection point X
> * session S2 executes some command
> * session S2 wakes up S1
> * now S2 needs to run one more command BUT only AFTER S1 traps into
> another injection point Y (and it is still the same CREATE INDEX)
> <------- tricky part here

Ah, OK.  So you want to have one single command, still wait through
two injection points inside it.  I am wondering about one thing: do
you really require that?  Could it be simpler to have two
permutations, each one of them using one wait point to check your two
scenarios?

> So, my proposal options:
> a) tell me if there's a clear solution I missed
> b) for 'wait' injection_point - learn isolation tester to detect it
> and implement logic like 'S2_query(S1 traps Y)'
> c) learn isolation tester to treat 'notice' from injection_point the
> same way as RAISE NOTICE + (preferable) add possibility to
> apply 'notice' and 'wait' for the same injection point (like
> 'wait+notice')
> d) add injection_point_await - utility to wait until injected point is not
> "waited" by some backend
>
> What do you think? Any other ideas?

Something close to what you are suggested in b), that can be defined
in the specs, sounds like a natural solution to me.  It also feels
like a better approach from the spec's reader perspective, as well:
this would document multiple wait steps in the test itself.
--
Michael

Вложения

Re: isolation tester limitation in case of multiple injection points in a single command

От
Mihail Nikalayeu
Дата:
Hello, Michael!

Michael Paquier <michael@paquier.xyz>:
> Ah, OK.  So you want to have one single command, still wait through
> two injection points inside it.  I am wondering about one thing: do
> you really require that?  Could it be simpler to have two
> permutations, each one of them using one wait point to check your two
> scenarios?

Good point, I reviewed all 4 types of permutations - and I was able to
reduce it to 1 of such type.

permutation
    s3_start_create_index(s1_start_upsert, s2_start_upsert)
    s1_start_upsert
    s4_wakeup_define_index_before_set_valid
    s2_start_upsert(s1_start_upsert)
    s4_wakeup_s1_from_invalidate_catalog_snapshot
    s4_wakeup_s2
    s4_wakeup_s1 <---- here

In human words it like this:

permutation
    s3 creates new index and hangs before marking it as valid
    s1 starts UPSERT, caches arbiter indexes and hangs in
InvalidateCatalogSnapshot
    s4 wakes up CREATE INDEX - new index now valid
    concurrent upsert s2 is started and hangs just before insertion
    s4 wakes up s1 - old update reads index definitions, goes throw
check_exclusion_or_unique_constraint and hangs before insertion
    s4 wakes up s2 - concurrent upsert inserts new tuples and finishes
    s4 wakes up s1 - initial upsert going to insert tuple and receives error

So, I have to hang/wake up s1 two times:
* once it cached old arbiters and before it read index definitions
* once it decides it is OK to do insertions

> But AFAIU injection_point's 'notice' is a totally different type of notice
> compared to RAISE NOTICE - so, isolation_tester just ignores it.
I was wrong here - it respects 'notice', I was using it in the wrong order.

This is NOT working (hangs)
permutation
    s1_notice
    s2_noop(s1_notice notices 1)
    s2_next

But this is working:
permutation
    s2_noop(s1_notice notices 1)
    s1_notice
    s2_next

So, it looks like option C ('notice+wait') feels like the simplest
solution for me.

Best regards,
Mikhail.