Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit759d9d6

Browse files
committed
Add simple tests of EvalPlanQual using the isolationtester infrastructure.
Much more could be done here, but at least now we have *some* automatedtest coverage of that mechanism. In particular this tests the writable-CTEcase reported by Phil Sorber.In passing, remove isolationtester's arbitrary restriction on the number ofsteps in a permutation list. I used this so that a single spec file couldbe used to run several related test scenarios, but there are other possiblereasons to want a step series that's not exactly a permutation. Improvedocumentation and fix a couple other nits as well.
1 parent7c1719b commit759d9d6

File tree

5 files changed

+176
-38
lines changed

5 files changed

+176
-38
lines changed

‎src/test/isolation/README

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,42 @@ src/test/isolation/README
33
Isolation tests
44
===============
55

6-
This directory contains a set of tests for the serializable isolation level.
7-
Testing isolation requires running multiple overlapping transactions,
8-
which requires multiple concurrent connections, and therefore can't be
9-
tested using the normal pg_regress program.
6+
This directory contains a set of tests for concurrent behaviors in
7+
PostgreSQL. These tests require running multiple interacting transactions,
8+
which requires management of multiple concurrent connections, and therefore
9+
can't be tested using the normal pg_regress program. The name "isolation"
10+
comes from the fact that the original motivation was to test the
11+
serializable isolation level; but tests for other sorts of concurrent
12+
behaviors have been added as well.
1013

1114
To run the tests, you need to have a server running at the default port
1215
expected by libpq. (You can set PGPORT and so forth in your environment
1316
to control this.) Then run
1417
gmake installcheck
15-
Note that the prepared-transactions test will not pass unless you have
16-
the server's max_prepared_transactions parameter set to at least 3.
17-
18-
To represent a test with overlapping transactions, we use a test specification
19-
file with a custom syntax, which is described in the next section.
18+
To run just specific test(s), you can do something like
19+
./pg_isolation_regress fk-contention fk-deadlock
20+
(look into the specs/ subdirectory to see the available tests).
21+
22+
Note that the prepared-transactions test requires the server's
23+
max_prepared_transactions parameter to be set to at least 3. We have
24+
provided a variant expected-output file that allows the test to "pass"
25+
when max_prepared_transactions has its default value of zero, but of
26+
course that is not really exercising the feature.
27+
28+
To define tests with overlapping transactions, we use test specification
29+
files with a custom syntax, which is described in the next section. To add
30+
a new test, place a spec file in the specs/ subdirectory, add the expected
31+
output in the expected/ subdirectory, and add the test's name to the
32+
isolation_schedule file.
2033

2134
isolationtester is a program that uses libpq to open multiple connections,
2235
and executes a test specified by a spec file. A libpq connection string
2336
specifies the server and database to connect to; defaults derived from
2437
environment variables are used otherwise.
2538

2639
pg_isolation_regress is a tool similar to pg_regress, but instead of using
27-
psql to execute a test, it uses isolationtester.
40+
psql to execute a test, it uses isolationtester. It accepts all the same
41+
command-line arguments as pg_regress.
2842

2943

3044
Test specification
@@ -36,48 +50,65 @@ subdirectory. A test specification consists of four parts, in this order:
3650
setup { <SQL> }
3751

3852
The given SQL block is executed once, in one session only, before running
39-
the test. Create any test tables orsuchobjects here. This part is
40-
optional.
53+
the test. Create any test tables orother requiredobjects here. This
54+
part isoptional.
4155

4256
teardown { <SQL> }
4357

4458
The teardown SQL block is executed once after the test is finished. Use
45-
this to clean up, e.g dropping any test tables. This part is optional.
59+
this to clean up in preparation for the next permutation, e.g dropping
60+
any test tables created by setup. This part is optional.
4661

4762
session "<name>"
4863

49-
Each session is executed in a separate connection. A session consists
50-
of four parts: setup, teardown and one or more steps. The per-session
64+
There are normally several "session" parts in a spec file. Each
65+
session is executed in its own connection. A session part consists
66+
of three parts: setup, teardown and one or more "steps". The per-session
5167
setup and teardown parts have the same syntax as the per-test setup and
52-
teardown described above, but they are executed in every session,
53-
before and after each permutation. The setup part typically contains a
54-
"BEGIN" command to begin a transaction.
68+
teardown described above, but they are executed in each session. The
69+
setup part typically contains a "BEGIN" command to begin a transaction.
5570

56-
Each step hasa syntax of
71+
Each step hasthe syntax
5772

5873
step "<name>" { <SQL> }
5974

60-
where <name> is auniquename identifying this step, and SQL is a SQL
61-
statement(or statements, separated by semicolons) that is executed in the
62-
step.
75+
where <name> is a name identifying this step, and SQL is a SQL statement
76+
(or statements, separated by semicolons) that is executed in the step.
77+
Step names must be unique across the whole spec file.
6378

6479
permutation "<step name>" ...
6580

6681
A permutation line specifies a list of steps that are run in that order.
67-
If no permutation lines are given, the test program automatically generates
68-
all possible overlapping orderings of the given sessions.
82+
Any number of permutation lines can appear. If no permutation lines are
83+
given, the test program automatically generates all possible orderings
84+
of the steps from each session (running the steps of any one session in
85+
order). Note that the list of steps in a manually specified
86+
"permutation" line doesn't actually have to be a permutation of the
87+
available steps; it could for instance repeat some steps more than once,
88+
or leave others out.
6989

7090
Lines beginning with a # are considered comments.
7191

92+
For each permutation of the session steps (whether these are manually
93+
specified in the spec file, or automatically generated), the isolation
94+
tester runs the main setup part, then per-session setup parts, then
95+
the selected session steps, then per-session teardown, then the main
96+
teardown script. Each selected step is sent to the connection associated
97+
with its session.
98+
7299

73100
Support for blocking commands
74101
=============================
75102

76-
Eachspec may contain commands that block until further action has been taken
103+
Eachstep may contain commands that block until further action has been taken
77104
(most likely, some other session runs a step that unblocks it or causes a
78-
deadlock).Such a spec needs to be careful to manually specify valid
105+
deadlock).A test that uses this ability must manually specify valid
79106
permutations, i.e. those that would not expect a blocked session to execute a
80-
command. If the spec fails to follow that rule, the spec is aborted.
107+
command. If the test fails to follow that rule, the test is aborted.
108+
109+
Currently, at most one step can be waiting at a time. As long as one
110+
step is waiting, subsequent steps are run to completion synchronously.
81111

82-
Only one command can be waiting at a time. As long as one command is waiting,
83-
other commands are run to completion synchronously.
112+
Note that isolationtester recognizes that a command has blocked by looking
113+
to see if it is shown as waiting in the pg_locks view; therefore, only
114+
blocks on heavyweight locks will be detected.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
Parsed test spec with 3 sessions
2+
3+
starting permutation: wx1 wx2 c1 c2 read
4+
step wx1: UPDATE accounts SET balance = balance - 200 WHERE accountid = 'checking';
5+
step wx2: UPDATE accounts SET balance = balance + 450 WHERE accountid = 'checking'; <waiting ...>
6+
step c1: COMMIT;
7+
step wx2: <... completed>
8+
step c2: COMMIT;
9+
step read: SELECT * FROM accounts ORDER BY accountid;
10+
accountid balance
11+
12+
checking 850
13+
savings 600
14+
15+
starting permutation: wy1 wy2 c1 c2 read
16+
step wy1: UPDATE accounts SET balance = balance + 500 WHERE accountid = 'checking';
17+
step wy2: UPDATE accounts SET balance = balance + 1000 WHERE accountid = 'checking' AND balance < 1000; <waiting ...>
18+
step c1: COMMIT;
19+
step wy2: <... completed>
20+
step c2: COMMIT;
21+
step read: SELECT * FROM accounts ORDER BY accountid;
22+
accountid balance
23+
24+
checking 1100
25+
savings 600
26+
27+
starting permutation: upsert1 upsert2 c1 c2 read
28+
step upsert1:
29+
WITH upsert AS
30+
(UPDATE accounts SET balance = balance + 500
31+
WHERE accountid = 'savings'
32+
RETURNING accountid)
33+
INSERT INTO accounts SELECT 'savings', 500
34+
WHERE NOT EXISTS (SELECT 1 FROM upsert);
35+
36+
step upsert2:
37+
WITH upsert AS
38+
(UPDATE accounts SET balance = balance + 1234
39+
WHERE accountid = 'savings'
40+
RETURNING accountid)
41+
INSERT INTO accounts SELECT 'savings', 1234
42+
WHERE NOT EXISTS (SELECT 1 FROM upsert);
43+
<waiting ...>
44+
step c1: COMMIT;
45+
step upsert2: <... completed>
46+
step c2: COMMIT;
47+
step read: SELECT * FROM accounts ORDER BY accountid;
48+
accountid balance
49+
50+
checking 600
51+
savings 2334

‎src/test/isolation/isolation_schedule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ test: prepared-transactions
1313
test: fk-contention
1414
test: fk-deadlock
1515
test: fk-deadlock2
16+
test: eval-plan-qual

‎src/test/isolation/isolationtester.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -395,15 +395,9 @@ run_named_permutations(TestSpec * testspec)
395395
Permutation*p=testspec->permutations[i];
396396
Step**steps;
397397

398-
if (p->nsteps!=nallsteps)
399-
{
400-
fprintf(stderr,"invalid number of steps in permutation %d\n",i+1);
401-
exit_nicely();
402-
}
403-
404398
steps=malloc(p->nsteps*sizeof(Step*));
405399

406-
/* Find all the named stepsfrom the lookup table */
400+
/* Find all the named stepsusing the lookup table */
407401
for (j=0;j<p->nsteps;j++)
408402
{
409403
Step**this= (Step**)bsearch(p->stepnames[j],allsteps,
@@ -418,7 +412,9 @@ run_named_permutations(TestSpec * testspec)
418412
steps[j]=*this;
419413
}
420414

415+
/* And run them */
421416
run_permutation(testspec,p->nsteps,steps);
417+
422418
free(steps);
423419
}
424420
}
@@ -483,6 +479,8 @@ report_two_error_messages(Step *step1, Step *step2)
483479
free(step2->errormsg);
484480
step2->errormsg=NULL;
485481
}
482+
483+
free(prefix);
486484
}
487485

488486
/*
@@ -700,7 +698,7 @@ try_complete_step(Step *step, int flags)
700698

701699
FD_ZERO(&read_set);
702700

703-
while (flags&STEP_NONBLOCK&&PQisBusy(conn))
701+
while ((flags&STEP_NONBLOCK)&&PQisBusy(conn))
704702
{
705703
FD_SET(sock,&read_set);
706704
timeout.tv_sec=0;
@@ -739,7 +737,8 @@ try_complete_step(Step *step, int flags)
739737
}
740738
elseif (!PQconsumeInput(conn))/* select(): data available */
741739
{
742-
fprintf(stderr,"PQconsumeInput failed: %s",PQerrorMessage(conn));
740+
fprintf(stderr,"PQconsumeInput failed: %s\n",
741+
PQerrorMessage(conn));
743742
exit_nicely();
744743
}
745744
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Tests for the EvalPlanQual mechanism
2+
#
3+
# EvalPlanQual is used in READ COMMITTED isolation level to attempt to
4+
# re-execute UPDATE and DELETE operations against rows that were updated
5+
# by some concurrent transaction.
6+
7+
setup
8+
{
9+
CREATETABLEaccounts (accountidtextPRIMARYKEY,balancenumericnotnull);
10+
INSERTINTOaccountsVALUES ('checking',600), ('savings',600);
11+
}
12+
13+
teardown
14+
{
15+
DROPTABLEaccounts;
16+
}
17+
18+
session"s1"
19+
setup{BEGINISOLATIONLEVELREADCOMMITTED; }
20+
# wx1 then wx2 checks the basic case of re-fetching up-to-date values
21+
step"wx1"{UPDATEaccountsSETbalance=balance-200WHEREaccountid='checking'; }
22+
# wy1 then wy2 checks the case where quals pass then fail
23+
step"wy1"{UPDATEaccountsSETbalance=balance+500WHEREaccountid='checking'; }
24+
# upsert tests are to check writable-CTE cases
25+
step"upsert1"{
26+
WITHupsertAS
27+
(UPDATEaccountsSETbalance=balance+500
28+
WHEREaccountid='savings'
29+
RETURNINGaccountid)
30+
INSERTINTOaccountsSELECT'savings',500
31+
WHERENOTEXISTS (SELECT1FROMupsert);
32+
}
33+
step"c1"{COMMIT; }
34+
35+
session"s2"
36+
setup{BEGINISOLATIONLEVELREADCOMMITTED; }
37+
step"wx2"{UPDATEaccountsSETbalance=balance+450WHEREaccountid='checking'; }
38+
step"wy2"{UPDATEaccountsSETbalance=balance+1000WHEREaccountid='checking'ANDbalance<1000; }
39+
step"upsert2"{
40+
WITHupsertAS
41+
(UPDATEaccountsSETbalance=balance+1234
42+
WHEREaccountid='savings'
43+
RETURNINGaccountid)
44+
INSERTINTOaccountsSELECT'savings',1234
45+
WHERENOTEXISTS (SELECT1FROMupsert);
46+
}
47+
step"c2"{COMMIT; }
48+
49+
session"s3"
50+
setup{BEGINISOLATIONLEVELREADCOMMITTED; }
51+
step"read"{SELECT*FROMaccountsORDERBYaccountid; }
52+
teardown{COMMIT; }
53+
54+
permutation"wx1""wx2""c1""c2""read"
55+
permutation"wy1""wy2""c1""c2""read"
56+
permutation"upsert1""upsert2""c1""c2""read"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp