Skip to content

Commit e88fcc1

Browse files
Marina Polyakovavbwagner
Marina Polyakova
authored andcommitted
Pgbench Fix Get the default transaction isolation level from PGOPTIONS
To make PGOPTIONS and the benchmarking option --default-isolation-level consistent, add the Read Uncommitted isolation level to the latter. + code cleanup
1 parent 3b531a5 commit e88fcc1

File tree

3 files changed

+116
-37
lines changed

3 files changed

+116
-37
lines changed

doc/src/sgml/ref/pgbench.sgml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
346346
<para>
347347
Set the default transaction isolation level:
348348
<itemizedlist>
349+
<listitem>
350+
<para><literal>RUC</>: Read Uncommitted</para>
351+
</listitem>
349352
<listitem>
350353
<para><literal>RC</>: Read Committed</para>
351354
</listitem>

src/bin/pgbench/pgbench.c

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ static const BuiltinScript builtin_script[] =
449449
/* Default transaction isolation level */
450450
typedef enum DefaultIsolationLevel
451451
{
452+
READ_UNCOMMITTED,
452453
READ_COMMITTED,
453454
REPEATABLE_READ,
454455
SERIALIZABLE,
@@ -457,12 +458,24 @@ typedef enum DefaultIsolationLevel
457458

458459
DefaultIsolationLevel default_isolation_level = READ_COMMITTED;
459460

460-
static const char *DEFAULT_ISOLATION_LEVEL_ABBREVIATION[] = {"RC", "RR", "S"};
461+
static const char *DEFAULT_ISOLATION_LEVEL_ABBREVIATION[] = {
462+
"RUC",
463+
"RC",
464+
"RR",
465+
"S"
466+
};
461467
static const char *DEFAULT_ISOLATION_LEVEL_SQL[] = {
468+
"read uncommitted",
462469
"read committed",
463470
"repeatable read",
464471
"serializable"
465472
};
473+
static const char *DEFAULT_ISOLATION_LEVEL_SHELL[] = {
474+
"read\\ uncommitted",
475+
"read\\ committed",
476+
"repeatable\\ read",
477+
"serializable"
478+
};
466479

467480
/*
468481
* For the failures during script execution.
@@ -2708,9 +2721,9 @@ doLog(TState *thread, CState *st, instr_time *now,
27082721
if (throttle_delay)
27092722
fprintf(logfile, " %.0f", lag);
27102723
if (max_tries > 1)
2711-
fprintf(logfile, " " INT64_FORMAT " " INT64_FORMAT,
2712-
st->retries.serialization,
2713-
st->retries.deadlocks);
2724+
fprintf(logfile, " " INT64_FORMAT " " INT64_FORMAT,
2725+
st->retries.serialization,
2726+
st->retries.deadlocks);
27142727
fputc('\n', logfile);
27152728
}
27162729
}
@@ -3398,16 +3411,16 @@ process_backslash_command(PsqlScanState sstate, const char *source)
33983411
}
33993412

34003413
/*
3401-
* Returns the same command where all continuous blocks of whitespaces are
3402-
* replaced by one space symbol.
3414+
* Returns the same text where all continuous blocks of whitespaces are replaced
3415+
* by one space symbol.
34033416
*
34043417
* Returns a malloc'd string.
34053418
*/
34063419
static char *
3407-
normalize_whitespaces(const char *command)
3420+
normalize_whitespaces(const char *text)
34083421
{
3409-
const char *ptr = command;
3410-
char *buffer = pg_malloc(strlen(command) + 1);
3422+
const char *ptr = text;
3423+
char *buffer = pg_malloc(strlen(text) + 1);
34113424
int length = 0;
34123425

34133426
while (*ptr)
@@ -4065,6 +4078,39 @@ main(int argc, char **argv)
40654078
pgport = env;
40664079
else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
40674080
login = env;
4081+
if ((env = getenv("PGOPTIONS")) != NULL && *env != '\0')
4082+
{
4083+
/* search for the default transaction isolation level value */
4084+
char *pgoptions = normalize_whitespaces(env);
4085+
const char *ptr = pgoptions;
4086+
int level;
4087+
4088+
while (*ptr)
4089+
{
4090+
if (isspace((unsigned char) *ptr))
4091+
ptr++;
4092+
if (strncmp(ptr, "-c ", 3) == 0 &&
4093+
pg_strncasecmp(ptr + 3, "default_transaction_isolation=", 30) == 0)
4094+
{
4095+
ptr = ptr + 33;
4096+
for (level = 0; level < NUM_DEFAULT_ISOLATION_LEVEL; level++)
4097+
{
4098+
const char *level_shell = DEFAULT_ISOLATION_LEVEL_SHELL[
4099+
level];
4100+
int level_shell_len = strlen(level_shell);
4101+
const char *next = ptr + level_shell_len;
4102+
4103+
if (pg_strncasecmp(ptr, level_shell, level_shell_len) == 0
4104+
&& (*next == '\0' || isspace((unsigned char) *next)))
4105+
default_isolation_level = level;
4106+
}
4107+
}
4108+
while (*ptr && !isspace((unsigned char) *ptr))
4109+
ptr++;
4110+
}
4111+
4112+
pg_free(pgoptions);
4113+
}
40684114

40694115
state = (CState *) pg_malloc(sizeof(CState));
40704116
memset(state, 0, sizeof(CState));

src/bin/pgbench/t/002_serialization_and_deadlock_failures.pl

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,31 @@
44
use Config;
55
use PostgresNode;
66
use TestLib;
7-
use Test::More tests => 59;
7+
use Test::More tests => 76;
88

99
use constant
1010
{
11-
READ_COMMITTED => 0,
12-
REPEATABLE_READ => 1,
13-
SERIALIZABLE => 2,
11+
READ_UNCOMMITTED => 0,
12+
READ_COMMITTED => 1,
13+
REPEATABLE_READ => 2,
14+
SERIALIZABLE => 3,
1415
};
1516

16-
my @isolation_level_sql = ('read committed', 'repeatable read', 'serializable');
17-
my @isolation_level_abbreviations = ('RC', 'RR', 'S');
17+
my @isolation_level_sql = (
18+
'read uncommitted',
19+
'read committed',
20+
'repeatable read',
21+
'serializable');
22+
my @isolation_level_abbreviations = ('RUC', 'RC', 'RR', 'S');
1823

1924
# The keys of advisory locks for testing deadlock failures:
2025
use constant
2126
{
22-
TRANSACTION_BEGINS => 3,
23-
DEADLOCK_1 => 4,
24-
WAIT_PGBENCH_2 => 5,
25-
DEADLOCK_2 => 6,
26-
TRANSACTION_ENDS => 7,
27+
TRANSACTION_BEGINS => 4,
28+
DEADLOCK_1 => 5,
29+
WAIT_PGBENCH_2 => 6,
30+
DEADLOCK_2 => 7,
31+
TRANSACTION_ENDS => 8,
2732
};
2833

2934
# Test concurrent update in table row with different default transaction
@@ -33,7 +38,7 @@
3338
$node->start;
3439
$node->safe_psql('postgres',
3540
'CREATE UNLOGGED TABLE xy (x integer, y integer); '
36-
. 'INSERT INTO xy VALUES (1, 2), (2, 3);');
41+
. 'INSERT INTO xy VALUES (1, 2);');
3742

3843
my $script_serialization = $node->basedir . '/pgbench_script_serialization';
3944
append_to_file($script_serialization,
@@ -111,7 +116,8 @@ sub test_pgbench_default_transaction_isolation_level_and_serialization_failures
111116
\$err_pgbench;
112117

113118
# Wait until pgbench also tries to acquire the same advisory lock:
114-
do {
119+
do
120+
{
115121
$in_psql =
116122
"select * from pg_locks where "
117123
. "locktype = 'advisory' and "
@@ -169,19 +175,32 @@ sub test_pgbench_default_transaction_isolation_level_and_serialization_failures
169175
. $isolation_level_sql
170176
. ": check processed transactions");
171177

172-
my $regex =
173-
($isolation_level == READ_COMMITTED)
174-
? qr{^((?!number of failures)(.|\n))*$}
175-
: qr{number of failures: [1-9]\d* \([1-9]\d*\.\d* %\)};
178+
my ($regex);
179+
180+
if ($isolation_level == READ_UNCOMMITTED ||
181+
$isolation_level == READ_COMMITTED)
182+
{
183+
$regex = qr{^((?!number of failures)(.|\n))*$};
184+
}
185+
else
186+
{
187+
$regex = qr{number of failures: [1-9]\d* \([1-9]\d*\.\d* %\)};
188+
}
176189

177190
like($out_pgbench,
178191
$regex,
179192
"concurrent update: $isolation_level_sql: check failures");
180193

181-
$regex =
182-
($isolation_level == READ_COMMITTED)
183-
? qr{^((?!client 0 got a serialization failure \(try 1/1\))(.|\n))*$}
184-
: qr{client 0 got a serialization failure \(try 1/1\)};
194+
if ($isolation_level == READ_UNCOMMITTED ||
195+
$isolation_level == READ_COMMITTED)
196+
{
197+
$regex =
198+
qr{^((?!client 0 got a serialization failure \(try 1/1\))(.|\n))*$};
199+
}
200+
else
201+
{
202+
$regex = qr{client 0 got a serialization failure \(try 1/1\)};
203+
}
185204

186205
like($err_pgbench,
187206
$regex,
@@ -228,7 +247,8 @@ sub test_pgbench_serialization_failures_retry
228247
\$err_pgbench;
229248

230249
# Wait until pgbench also tries to acquire the same advisory lock:
231-
do {
250+
do
251+
{
232252
$in_psql =
233253
"select * from pg_locks where "
234254
. "locktype = 'advisory' and "
@@ -341,7 +361,8 @@ sub test_pgbench_deadlock_failures
341361
$h1 = IPC::Run::start \@command1, \$in1, \$out1, \$err1;
342362

343363
# Wait until the first pgbench also tries to acquire the same advisory lock:
344-
do {
364+
do
365+
{
345366
$in_psql =
346367
"select case count(*) "
347368
. "when 0 then '" . WAIT_PGBENCH_2 . "_zero' "
@@ -369,7 +390,8 @@ sub test_pgbench_deadlock_failures
369390

370391
# Wait until the second pgbench tries to acquire the lock held by the first
371392
# pgbench:
372-
do {
393+
do
394+
{
373395
$in_psql =
374396
"select case count(*) "
375397
. "when 0 then '" . DEADLOCK_1 . "_zero' "
@@ -486,7 +508,8 @@ sub test_pgbench_deadlock_failures_retry
486508
$h1 = IPC::Run::start \@command1, \$in1, \$out1, \$err1;
487509

488510
# Wait until the first pgbench also tries to acquire the same advisory lock:
489-
do {
511+
do
512+
{
490513
$in_psql =
491514
"select case count(*) "
492515
. "when 0 then '" . WAIT_PGBENCH_2 . "_zero' "
@@ -514,7 +537,8 @@ sub test_pgbench_deadlock_failures_retry
514537

515538
# Wait until the second pgbench tries to acquire the lock held by the first
516539
# pgbench:
517-
do {
540+
do
541+
{
518542
$in_psql =
519543
"select case count(*) "
520544
. "when 0 then '" . DEADLOCK_1 . "_zero' "
@@ -557,7 +581,8 @@ sub test_pgbench_deadlock_failures_retry
557581
$h_psql->pump() until $out_psql =~ /pg_advisory_unlock_@{[ WAIT_PGBENCH_2 ]}/;
558582

559583
# Wait until pgbenches try to acquire the locks held by the psql session:
560-
do {
584+
do
585+
{
561586
$in_psql =
562587
"select case count(*) "
563588
. "when 0 then '" . TRANSACTION_BEGINS . "_zero' "
@@ -573,7 +598,8 @@ sub test_pgbench_deadlock_failures_retry
573598
$h_psql->pump() while length $in_psql;
574599
} while ($out_psql !~ /@{[ TRANSACTION_BEGINS ]}_not_zero/);
575600

576-
do {
601+
do
602+
{
577603
$in_psql =
578604
"select case count(*) "
579605
. "when 0 then '" . TRANSACTION_ENDS . "_zero' "
@@ -678,6 +704,8 @@ sub test_pgbench_deadlock_failures_retry
678704
. ": check the retried transaction");
679705
}
680706

707+
test_pgbench_default_transaction_isolation_level_and_serialization_failures(
708+
READ_UNCOMMITTED);
681709
test_pgbench_default_transaction_isolation_level_and_serialization_failures(
682710
READ_COMMITTED);
683711
test_pgbench_default_transaction_isolation_level_and_serialization_failures(
@@ -688,10 +716,12 @@ sub test_pgbench_deadlock_failures_retry
688716
test_pgbench_serialization_failures_retry(REPEATABLE_READ);
689717
test_pgbench_serialization_failures_retry(SERIALIZABLE);
690718

719+
test_pgbench_deadlock_failures(READ_UNCOMMITTED);
691720
test_pgbench_deadlock_failures(READ_COMMITTED);
692721
test_pgbench_deadlock_failures(REPEATABLE_READ);
693722
test_pgbench_deadlock_failures(SERIALIZABLE);
694723

724+
test_pgbench_deadlock_failures_retry(READ_UNCOMMITTED);
695725
test_pgbench_deadlock_failures_retry(READ_COMMITTED);
696726
test_pgbench_deadlock_failures_retry(REPEATABLE_READ);
697727
test_pgbench_deadlock_failures_retry(SERIALIZABLE);

0 commit comments

Comments
 (0)