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

Commit466a086

Browse files
committed
Test for a write cycles
1 parent6fb8e41 commit466a086

File tree

1 file changed

+114
-45
lines changed

1 file changed

+114
-45
lines changed
Lines changed: 114 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
###############################################################################
22
# Test of proper transaction isolation.
3+
# Based on Martin Kleppmann tests, https://github.com/ept/hermitage
34
###############################################################################
45

56
use strict;
67
use warnings;
78
use PostgresNode;
89
use TestLib;
9-
use Test::Moretests=>1;
10-
use DBI();
11-
use DBD::Pg();
10+
use Test::Moretests=>2;
11+
use DBI;
12+
use DBD::Pg':async';
1213

1314
subquery_row
1415
{
@@ -23,8 +24,16 @@ sub query_row
2324
subquery_exec
2425
{
2526
my ($dbi,$sql) =@_;
26-
print"query_exec('$sql')\n";
2727
my$rv =$dbi->do($sql) ||die;
28+
print"query_exec('$sql')\n";
29+
return$rv;
30+
}
31+
32+
subquery_exec_async
33+
{
34+
my ($dbi,$sql) =@_;
35+
my$rv =$dbi->do($sql, {pg_async=> PG_ASYNC}) ||die;
36+
print"query_exec('$sql')\n";
2837
return$rv;
2938
}
3039

@@ -50,33 +59,33 @@ sub PostgresNode::psql_fails {
5059
my$node1 = get_new_node("node1");
5160
$node1->init;
5261
$node1->append_conf('postgresql.conf',qq(
53-
max_prepared_transactions = 10
54-
shared_preload_libraries = 'pg_tsdtm'
62+
max_prepared_transactions = 10
63+
shared_preload_libraries = 'pg_tsdtm'
5564
));
5665
$node1->start;
5766

5867
# Setup second node
5968
my$node2 = get_new_node("node2");
6069
$node2->init;
6170
$node2->append_conf('postgresql.conf',qq(
62-
max_prepared_transactions = 10
63-
shared_preload_libraries = 'pg_tsdtm'
71+
max_prepared_transactions = 10
72+
shared_preload_libraries = 'pg_tsdtm'
6473
));
6574
$node2->start;
6675

67-
$node1->psql('postgres',"create extension pg_tsdtm;");
68-
$node1->psql('postgres',"create table t(u int primary key, v int)");
69-
$node1->psql('postgres',"insert into t(select generate_series(0, 9), 0)");
76+
$node1->psql('postgres',"create extension pg_tsdtm");
77+
$node1->psql('postgres',"create table t(id int primary key, v int)");
78+
$node1->psql('postgres',"insert into tvalues(1, 10)");
7079

71-
$node2->psql('postgres',"create extension pg_tsdtm;");
72-
$node2->psql('postgres',"create table t(u int primary key, v int)");
73-
$node2->psql('postgres',"insert into t(select generate_series(0, 9), 0)");
80+
$node2->psql('postgres',"create extension pg_tsdtm");
81+
$node2->psql('postgres',"create table t(id int primary key, v int)");
82+
$node2->psql('postgres',"insert into tvalues(2, 20)");
7483

7584
# we need two connections to each node (run two simultameous global tx)
76-
my$conn11 = DBI->connect('DBI:Pg:' .$node1->connstr('postgres'));
77-
my$conn21 = DBI->connect('DBI:Pg:' .$node2->connstr('postgres'));
78-
my$conn12 = DBI->connect('DBI:Pg:' .$node1->connstr('postgres'));
79-
my$conn22 = DBI->connect('DBI:Pg:' .$node2->connstr('postgres'));
85+
my$conn1a = DBI->connect('DBI:Pg:' .$node1->connstr('postgres'));
86+
my$conn2a = DBI->connect('DBI:Pg:' .$node2->connstr('postgres'));
87+
my$conn1b = DBI->connect('DBI:Pg:' .$node1->connstr('postgres'));
88+
my$conn2b = DBI->connect('DBI:Pg:' .$node2->connstr('postgres'));
8089

8190
subcount_total
8291
{
@@ -100,34 +109,94 @@ sub count_total
100109
return$tot;
101110
}
102111

112+
substart_global
113+
{
114+
my ($gtid,$c1,$c2) =@_;
115+
116+
query_exec($c1,"begin transaction");
117+
query_exec($c2,"begin transaction");
118+
my$snapshot = query_row($c1,"select dtm_extend('$gtid')");
119+
query_exec($c2,"select dtm_access($snapshot, '$gtid')");
120+
}
121+
122+
subcommit_global
123+
{
124+
my ($gtid,$c1,$c2) =@_;
125+
126+
query_exec($c1,"prepare transaction '$gtid'");
127+
query_exec($c2,"prepare transaction '$gtid'");
128+
query_exec($c1,"select dtm_begin_prepare('$gtid')");
129+
query_exec($c2,"select dtm_begin_prepare('$gtid')");
130+
my$csn = query_row($c1,"select dtm_prepare('$gtid', 0)");
131+
query_exec($c2,"select dtm_prepare('$gtid',$csn)");
132+
query_exec($c1,"select dtm_end_prepare('$gtid',$csn)");
133+
query_exec($c2,"select dtm_end_prepare('$gtid',$csn)");
134+
query_exec($c1,"commit prepared '$gtid'");
135+
query_exec($c2,"commit prepared '$gtid'");
136+
}
137+
103138
###############################################################################
104-
# Sanity check on dirty reads
139+
# Sanity check for dirty reads
140+
###############################################################################
141+
142+
start_global("gtx1",$conn1a,$conn2a);
143+
144+
query_exec($conn1a,"update t set v = v - 10 where id=1");
145+
146+
my$intermediate_total = count_total($conn1b,$conn2b);
147+
148+
query_exec($conn2a,"update t set v = v + 10 where id=2");
149+
150+
commit_global("gtx1",$conn1a,$conn2a);
151+
152+
is($intermediate_total, 30,"Check for absence of dirty reads");
153+
105154
###############################################################################
155+
# G0
156+
###############################################################################
157+
158+
my$fail = 0;
159+
$node1->psql('postgres',"update t set v = 10 where id = 2");
160+
$node2->psql('postgres',"update t set v = 20 where id = 2");
161+
162+
start_global("gtx2a",$conn1a,$conn2a);
163+
start_global("gtx2b",$conn1b,$conn2b);
164+
165+
query_exec($conn1a,"update t set v = 11 where id = 1");
166+
query_exec_async($conn1b,"update t set v = 12 where id = 1");
167+
168+
# last update should be locked
169+
$fail = 1if$conn1b->pg_ready != 0;
170+
171+
query_exec($conn2a,"update t set v = 21 where id = 2");
172+
commit_global("gtx2a",$conn1a,$conn2a);
173+
174+
# here transaction can continue
175+
$conn1b->pg_result;
176+
177+
my$v1 = query_row($conn1a,"select v from t where id = 1");
178+
my$v2 = query_row($conn2a,"select v from t where id = 2");
179+
180+
# we shouldn't see second's tx data
181+
$fail = 1if$v1 != 11or$v2 != 21;
182+
183+
query_exec($conn2b,"update t set v = 22 where id = 2");
184+
commit_global("gtx2b",$conn1b,$conn2b);
185+
186+
$v1 = query_row($conn1a,"select v from t where id = 1");
187+
$v2 = query_row($conn2a,"select v from t where id = 2");
188+
189+
$fail = 1if$v1 != 12or$v2 != 22;
190+
191+
is($fail, 0,"Global transactions prevents Write Cycles (G0)");
192+
193+
194+
195+
196+
197+
198+
199+
200+
106201

107-
my$gtid1 ="gtx1";
108-
109-
# start global tx
110-
query_exec($conn11,"begin transaction");
111-
query_exec($conn21,"begin transaction");
112-
my$snapshot = query_row($conn11,"select dtm_extend('$gtid1')");
113-
query_exec($conn21,"select dtm_access($snapshot, '$gtid1')");
114-
115-
# transfer some amount of integers to different node
116-
query_exec($conn11,"update t set v = v - 10 where u=1");
117-
my$intermediate_total = count_total($conn12,$conn22);
118-
query_exec($conn21,"update t set v = v + 10 where u=2");
119-
120-
# commit our global tx
121-
query_exec($conn11,"prepare transaction '$gtid1'");
122-
query_exec($conn21,"prepare transaction '$gtid1'");
123-
query_exec($conn11,"select dtm_begin_prepare('$gtid1')");
124-
query_exec($conn21,"select dtm_begin_prepare('$gtid1')");
125-
my$csn = query_row($conn11,"select dtm_prepare('$gtid1', 0)");
126-
query_exec($conn21,"select dtm_prepare('$gtid1',$csn)");
127-
query_exec($conn11,"select dtm_end_prepare('$gtid1',$csn)");
128-
query_exec($conn21,"select dtm_end_prepare('$gtid1',$csn)");
129-
query_exec($conn11,"commit prepared '$gtid1'");
130-
query_exec($conn21,"commit prepared '$gtid1'");
131-
132-
is($intermediate_total, 0,"Check for absence of dirty reads");
133202

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp