Make multixact test more robust

There was no guarantee that the SELECT FOR KEY SHARE queries actually
run in parallel. With unlucky timing, one query might finish before
the next one starts, so that the server doesn't need to create a
multixact. I got a failure like that on the CI:

    batch_others/test_multixact.py:56: in test_multixact
        assert(int(next_multixact_id) > int(next_multixact_id_old))
    E   AssertionError: assert 1 > 1
    E    +  where 1 = int('1')
    E    +  and   1 = int('1')

This could be reproduced by adding a random sleep in the runQuery
function, to make each query run at different times.

To fix, keep the transactions open after running the queries, so that
they will surely be open concurrently. With that, we can run the
queries serially, and don't need the 'multiprocessing' module anymore.

Fixes https://github.com/zenithdb/zenith/issues/196
This commit is contained in:
Heikki Linnakangas
2021-05-27 20:00:52 +03:00
parent 60ea26316e
commit d1d2d5ce69

View File

@@ -1,7 +1,6 @@
import pytest
import os
import psycopg2
import multiprocessing
pytest_plugins = ("fixtures.zenith_fixtures")
@@ -11,14 +10,6 @@ pytest_plugins = ("fixtures.zenith_fixtures")
# it only checks next_multixact_id field in restored pg_control,
# since we don't have functions to check multixact internals.
#
def runQuery(connstr):
con = psycopg2.connect(connstr)
con.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cur = con.cursor()
cur.execute('select * from t1 for key share;')
def test_multixact(pageserver, postgres, pg_bin, zenith_cli, base_dir):
# Create a branch for us
@@ -38,11 +29,16 @@ def test_multixact(pageserver, postgres, pg_bin, zenith_cli, base_dir):
# Lock entries in parallel connections to set multixact
nclients = 3
pool = multiprocessing.Pool(nclients)
args = [pg.connstr()] * nclients
pool.map(runQuery, args)
pool.close()
pool.join()
connections = []
for i in range(nclients):
con = psycopg2.connect(pg.connstr())
# Do not turn on autocommit. We want to hold the key-share locks.
con.cursor().execute('select * from t1 for key share;')
connections.append(con)
# We should have a multixact now. We can close the connections.
for c in connections:
c.close()
# force wal flush
cur.execute('checkpoint')