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

Commit1e504f0

Browse files
committed
Ignore inherited temp relations from other sessions when truncating
Inheritance trees can include temporary tables if the parent ispermanent, which makes possible the presence of multiple temporarychildren from different sessions. Trying to issue a TRUNCATE on theparent in this scenario causes a failure, so similarly to any otherqueries just ignore such cases, which makes TRUNCATE worktransparently.This makes truncation behave similarly to any other DML query working onthe parent table with queries which need to be work on the children. Aset of isolation tests is added to cover basic cases.Reported-by: Zhou DigoalAuthor: Amit Langote, Michael PaquierDiscussion:https://postgr.es/m/15565-ce67a48d0244436a@postgresql.orgBackpatch-through: 9.4
1 parent8528e3d commit1e504f0

File tree

4 files changed

+316
-3
lines changed

4 files changed

+316
-3
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,8 +1373,9 @@ ExecuteTruncate(TruncateStmt *stmt)
13731373
Relationrel;
13741374
boolrecurse=rv->inh;
13751375
Oidmyrelid;
1376+
LOCKMODElockmode=AccessExclusiveLock;
13761377

1377-
myrelid=RangeVarGetRelidExtended(rv,AccessExclusiveLock,
1378+
myrelid=RangeVarGetRelidExtended(rv,lockmode,
13781379
0,RangeVarCallbackForTruncate,
13791380
NULL);
13801381

@@ -1384,7 +1385,7 @@ ExecuteTruncate(TruncateStmt *stmt)
13841385
/* don't throw error for "TRUNCATE foo, foo" */
13851386
if (list_member_oid(relids,myrelid))
13861387
{
1387-
heap_close(rel,AccessExclusiveLock);
1388+
heap_close(rel,lockmode);
13881389
continue;
13891390
}
13901391

@@ -1405,7 +1406,7 @@ ExecuteTruncate(TruncateStmt *stmt)
14051406
ListCell*child;
14061407
List*children;
14071408

1408-
children=find_all_inheritors(myrelid,AccessExclusiveLock,NULL);
1409+
children=find_all_inheritors(myrelid,lockmode,NULL);
14091410

14101411
foreach(child,children)
14111412
{
@@ -1416,6 +1417,22 @@ ExecuteTruncate(TruncateStmt *stmt)
14161417

14171418
/* find_all_inheritors already got lock */
14181419
rel=heap_open(childrelid,NoLock);
1420+
1421+
/*
1422+
* It is possible that the parent table has children that are
1423+
* temp tables of other backends. We cannot safely access
1424+
* such tables (because of buffering issues), and the best
1425+
* thing to do is to silently ignore them. Note that this
1426+
* check is the same as one of the checks done in
1427+
* truncate_check_activity() called below, still it is kept
1428+
* here for simplicity.
1429+
*/
1430+
if (RELATION_IS_OTHER_TEMP(rel))
1431+
{
1432+
heap_close(rel,lockmode);
1433+
continue;
1434+
}
1435+
14191436
truncate_check_rel(RelationGetRelid(rel),rel->rd_rel);
14201437
truncate_check_activity(rel);
14211438

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
Parsed test spec with 2 sessions
2+
3+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_select_p s1_select_c s2_select_p s2_select_c
4+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
5+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
6+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
7+
step s1_select_p: SELECT a FROM inh_parent;
8+
a
9+
10+
1
11+
2
12+
3
13+
4
14+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
15+
a
16+
17+
3
18+
4
19+
step s2_select_p: SELECT a FROM inh_parent;
20+
a
21+
22+
1
23+
2
24+
5
25+
6
26+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
27+
a
28+
29+
5
30+
6
31+
32+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_update_p s1_update_c s1_select_p s1_select_c s2_select_p s2_select_c
33+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
34+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
35+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
36+
step s1_update_p: UPDATE inh_parent SET a = 11 WHERE a = 1;
37+
step s1_update_c: UPDATE inh_parent SET a = 13 WHERE a IN (3, 5);
38+
step s1_select_p: SELECT a FROM inh_parent;
39+
a
40+
41+
2
42+
11
43+
4
44+
13
45+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
46+
a
47+
48+
4
49+
13
50+
step s2_select_p: SELECT a FROM inh_parent;
51+
a
52+
53+
2
54+
11
55+
5
56+
6
57+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
58+
a
59+
60+
5
61+
6
62+
63+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s2_update_c s1_select_p s1_select_c s2_select_p s2_select_c
64+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
65+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
66+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
67+
step s2_update_c: UPDATE inh_parent SET a = 15 WHERE a IN (3, 5);
68+
step s1_select_p: SELECT a FROM inh_parent;
69+
a
70+
71+
1
72+
2
73+
3
74+
4
75+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
76+
a
77+
78+
3
79+
4
80+
step s2_select_p: SELECT a FROM inh_parent;
81+
a
82+
83+
1
84+
2
85+
6
86+
15
87+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
88+
a
89+
90+
6
91+
15
92+
93+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_delete_p s1_delete_c s1_select_p s1_select_c s2_select_p s2_select_c
94+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
95+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
96+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
97+
step s1_delete_p: DELETE FROM inh_parent WHERE a = 2;
98+
step s1_delete_c: DELETE FROM inh_parent WHERE a IN (4, 6);
99+
step s1_select_p: SELECT a FROM inh_parent;
100+
a
101+
102+
1
103+
3
104+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
105+
a
106+
107+
3
108+
step s2_select_p: SELECT a FROM inh_parent;
109+
a
110+
111+
1
112+
5
113+
6
114+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
115+
a
116+
117+
5
118+
6
119+
120+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s2_delete_c s1_select_p s1_select_c s2_select_p s2_select_c
121+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
122+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
123+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
124+
step s2_delete_c: DELETE FROM inh_parent WHERE a IN (4, 6);
125+
step s1_select_p: SELECT a FROM inh_parent;
126+
a
127+
128+
1
129+
2
130+
3
131+
4
132+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
133+
a
134+
135+
3
136+
4
137+
step s2_select_p: SELECT a FROM inh_parent;
138+
a
139+
140+
1
141+
2
142+
5
143+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
144+
a
145+
146+
5
147+
148+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_truncate_p s1_select_p s1_select_c s2_select_p s2_select_c
149+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
150+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
151+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
152+
step s1_truncate_p: TRUNCATE inh_parent;
153+
step s1_select_p: SELECT a FROM inh_parent;
154+
a
155+
156+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
157+
a
158+
159+
step s2_select_p: SELECT a FROM inh_parent;
160+
a
161+
162+
5
163+
6
164+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
165+
a
166+
167+
5
168+
6
169+
170+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s2_truncate_p s1_select_p s1_select_c s2_select_p s2_select_c
171+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
172+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
173+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
174+
step s2_truncate_p: TRUNCATE inh_parent;
175+
step s1_select_p: SELECT a FROM inh_parent;
176+
a
177+
178+
3
179+
4
180+
step s1_select_c: SELECT a FROM inh_temp_child_s1;
181+
a
182+
183+
3
184+
4
185+
step s2_select_p: SELECT a FROM inh_parent;
186+
a
187+
188+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
189+
a
190+
191+
192+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_begin s1_truncate_p s2_select_p s1_commit
193+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
194+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
195+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
196+
step s1_begin: BEGIN;
197+
step s1_truncate_p: TRUNCATE inh_parent;
198+
step s2_select_p: SELECT a FROM inh_parent; <waiting ...>
199+
step s1_commit: COMMIT;
200+
step s2_select_p: <... completed>
201+
a
202+
203+
5
204+
6
205+
206+
starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_begin s1_truncate_p s2_select_c s1_commit
207+
step s1_insert_p: INSERT INTO inh_parent VALUES (1), (2);
208+
step s1_insert_c: INSERT INTO inh_temp_child_s1 VALUES (3), (4);
209+
step s2_insert_c: INSERT INTO inh_temp_child_s2 VALUES (5), (6);
210+
step s1_begin: BEGIN;
211+
step s1_truncate_p: TRUNCATE inh_parent;
212+
step s2_select_c: SELECT a FROM inh_temp_child_s2;
213+
a
214+
215+
5
216+
6
217+
step s1_commit: COMMIT;

‎src/test/isolation/isolation_schedule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ test: fk-deadlock2
2727
test: eval-plan-qual
2828
test: lock-update-delete
2929
test: lock-update-traversal
30+
test: inherit-temp
3031
test: insert-conflict-do-nothing
3132
test: insert-conflict-do-nothing-2
3233
test: insert-conflict-do-update
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Tests for inheritance trees with temporary relations
2+
#
3+
# Inheritance trees are allowed to mix relations with different persistence
4+
# as long as a persistent child relation does not try to inherit from a
5+
# temporary parent. This checks several scenarios with SELECT, INSERT, UPDATE,
6+
# DELETE and TRUNCATE. Any temporary relation inheriting from the same
7+
# persistent parent should be isolated and handled only in its own session.
8+
9+
setup
10+
{
11+
CREATETABLEinh_parent (aint);
12+
}
13+
14+
teardown
15+
{
16+
DROPTABLEinh_parent;
17+
}
18+
19+
# Session 1 executes actions which act directly on both the parent and
20+
# its child. Abbreviation "c" is used for queries working on the child
21+
# and "p" on the parent.
22+
session"s1"
23+
setup
24+
{
25+
CREATETEMPORARYTABLEinh_temp_child_s1 ()INHERITS (inh_parent);
26+
}
27+
step"s1_begin" {BEGIN; }
28+
step"s1_truncate_p" {TRUNCATEinh_parent; }
29+
step"s1_select_p" {SELECTaFROMinh_parent; }
30+
step"s1_select_c" {SELECTaFROMinh_temp_child_s1; }
31+
step"s1_insert_p" {INSERTINTOinh_parentVALUES (1), (2); }
32+
step"s1_insert_c" {INSERTINTOinh_temp_child_s1VALUES (3), (4); }
33+
step"s1_update_p" {UPDATEinh_parentSETa=11WHEREa=1; }
34+
step"s1_update_c" {UPDATEinh_parentSETa=13WHEREaIN (3,5); }
35+
step"s1_delete_p" {DELETEFROMinh_parentWHEREa=2; }
36+
step"s1_delete_c" {DELETEFROMinh_parentWHEREaIN (4,6); }
37+
step"s1_commit" {COMMIT; }
38+
teardown
39+
{
40+
DROPTABLEinh_temp_child_s1;
41+
}
42+
43+
# Session 2 executes actions on the parent which act only on the child.
44+
session"s2"
45+
setup
46+
{
47+
CREATETEMPORARYTABLEinh_temp_child_s2 ()INHERITS (inh_parent);
48+
}
49+
step"s2_truncate_p" {TRUNCATEinh_parent; }
50+
step"s2_select_p" {SELECTaFROMinh_parent; }
51+
step"s2_select_c" {SELECTaFROMinh_temp_child_s2; }
52+
step"s2_insert_c" {INSERTINTOinh_temp_child_s2VALUES (5), (6); }
53+
step"s2_update_c" {UPDATEinh_parentSETa=15WHEREaIN (3,5); }
54+
step"s2_delete_c" {DELETEFROMinh_parentWHEREaIN (4,6); }
55+
teardown
56+
{
57+
DROPTABLEinh_temp_child_s2;
58+
}
59+
60+
# Check INSERT behavior across sessions
61+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
62+
63+
# Check UPDATE behavior across sessions
64+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s1_update_p""s1_update_c""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
65+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s2_update_c""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
66+
67+
# Check DELETE behavior across sessions
68+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s1_delete_p""s1_delete_c""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
69+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s2_delete_c""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
70+
71+
# Check TRUNCATE behavior across sessions
72+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s1_truncate_p""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
73+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s2_truncate_p""s1_select_p""s1_select_c""s2_select_p""s2_select_c"
74+
75+
# TRUNCATE on a parent tree does not block access to temporary child relation
76+
# of another session, and blocks when scanning the parent.
77+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s1_begin""s1_truncate_p""s2_select_p""s1_commit"
78+
permutation"s1_insert_p""s1_insert_c""s2_insert_c""s1_begin""s1_truncate_p""s2_select_c""s1_commit"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp