Skip to content

Commit ea3ad73

Browse files
committed
simplify initial partitioning locks
1 parent 1145931 commit ea3ad73

File tree

7 files changed

+84
-110
lines changed

7 files changed

+84
-110
lines changed

Diff for: hash.sql

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ DECLARE
2626
v_hashfunc TEXT;
2727

2828
BEGIN
29-
/* Acquire exclusive lock on parent */
30-
PERFORM @[email protected]_partitioned_relation(parent_relid);
31-
3229
IF partition_data = true THEN
3330
/* Acquire data modification lock */
34-
PERFORM @[email protected]_relation_modification(parent_relid);
31+
PERFORM @[email protected]_relation_modification(parent_relid);
32+
ELSE
33+
/* Acquire lock on parent */
34+
PERFORM @[email protected]_partitioned_relation(parent_relid);
3535
END IF;
3636

3737
PERFORM @[email protected]_relname(parent_relid);

Diff for: init.sql

+2-10
Original file line numberDiff line numberDiff line change
@@ -658,17 +658,9 @@ LANGUAGE C STRICT;
658658
/*
659659
* Lock relation to restrict concurrent modification of data.
660660
*/
661-
CREATE OR REPLACE FUNCTION @extschema@.lock_relation_modification(
661+
CREATE OR REPLACE FUNCTION @extschema@.prevent_relation_modification(
662662
REGCLASS)
663-
RETURNS VOID AS 'pg_pathman', 'lock_relation_modification'
664-
LANGUAGE C STRICT;
665-
666-
/*
667-
* Check if we can distribute data without bad consequences.
668-
*/
669-
CREATE OR REPLACE FUNCTION @[email protected]_blocking_partitioning_checks(
670-
REGCLASS)
671-
RETURNS VOID AS 'pg_pathman', 'common_blocking_partitioning_checks'
663+
RETURNS VOID AS 'pg_pathman', 'prevent_relation_modification'
672664
LANGUAGE C STRICT;
673665

674666

Diff for: range.sql

+30-45
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,12 @@ DECLARE
9494
i INTEGER;
9595

9696
BEGIN
97-
/* Acquire exclusive lock on parent */
98-
PERFORM @[email protected]_partitioned_relation(parent_relid);
99-
10097
IF partition_data = true THEN
101-
/* Perform some checks regarding the blocking partitioning */
102-
PERFORM @extschema@.common_blocking_partitioning_checks(parent_relid);
103-
104-
/* Acquire data modification lock (prevent further modifications) */
105-
PERFORM @extschema@.lock_relation_modification(parent_relid);
98+
/* Acquire data modification lock */
99+
PERFORM @extschema@.prevent_relation_modification(parent_relid);
100+
ELSE
101+
/* Acquire lock on parent */
102+
PERFORM @extschema@.lock_partitioned_relation(parent_relid);
106103
END IF;
107104

108105
PERFORM @[email protected]_relname(parent_relid);
@@ -196,15 +193,12 @@ DECLARE
196193
i INTEGER;
197194

198195
BEGIN
199-
/* Acquire exclusive lock on parent */
200-
PERFORM @[email protected]_partitioned_relation(parent_relid);
201-
202196
IF partition_data = true THEN
203-
/* Perform some checks regarding the blocking partitioning */
204-
PERFORM @extschema@.common_blocking_partitioning_checks(parent_relid);
205-
206-
/* Acquire data modification lock (prevent further modifications) */
207-
PERFORM @extschema@.lock_relation_modification(parent_relid);
197+
/* Acquire data modification lock */
198+
PERFORM @extschema@.prevent_relation_modification(parent_relid);
199+
ELSE
200+
/* Acquire lock on parent */
201+
PERFORM @extschema@.lock_partitioned_relation(parent_relid);
208202
END IF;
209203

210204
PERFORM @[email protected]_relname(parent_relid);
@@ -296,15 +290,12 @@ DECLARE
296290
part_count INTEGER := 0;
297291

298292
BEGIN
299-
/* Acquire exclusive lock on parent */
300-
PERFORM @[email protected]_partitioned_relation(parent_relid);
301-
302293
IF partition_data = true THEN
303-
/* Perform some checks regarding the blocking partitioning */
304-
PERFORM @extschema@.common_blocking_partitioning_checks(parent_relid);
305-
306-
/* Acquire data modification lock (prevent further modifications) */
307-
PERFORM @extschema@.lock_relation_modification(parent_relid);
294+
/* Acquire data modification lock */
295+
PERFORM @extschema@.prevent_relation_modification(parent_relid);
296+
ELSE
297+
/* Acquire lock on parent */
298+
PERFORM @extschema@.lock_partitioned_relation(parent_relid);
308299
END IF;
309300

310301
PERFORM @[email protected]_relname(parent_relid);
@@ -369,15 +360,12 @@ DECLARE
369360
part_count INTEGER := 0;
370361

371362
BEGIN
372-
/* Acquire exclusive lock on parent */
373-
PERFORM @[email protected]_partitioned_relation(parent_relid);
374-
375363
IF partition_data = true THEN
376-
/* Perform some checks regarding the blocking partitioning */
377-
PERFORM @extschema@.common_blocking_partitioning_checks(parent_relid);
378-
379-
/* Acquire data modification lock (prevent further modifications) */
380-
PERFORM @extschema@.lock_relation_modification(parent_relid);
364+
/* Acquire data modification lock */
365+
PERFORM @extschema@.prevent_relation_modification(parent_relid);
366+
ELSE
367+
/* Acquire lock on parent */
368+
PERFORM @extschema@.lock_partitioned_relation(parent_relid);
381369
END IF;
382370

383371
PERFORM @[email protected]_relname(parent_relid);
@@ -518,12 +506,11 @@ BEGIN
518506
v_part_relname := @[email protected]_relname(p_partition);
519507
v_parent_relid = @[email protected]_parent_of_partition(p_partition);
520508

521-
/* Acquire exclusive lock on parent */
509+
/* Acquire lock on parent */
522510
PERFORM @[email protected]_partitioned_relation(v_parent_relid);
523511

524512
/* Acquire data modification lock (prevent further modifications) */
525-
PERFORM @[email protected]_blocking_partitioning_checks(p_partition);
526-
PERFORM @[email protected]_relation_modification(p_partition);
513+
PERFORM @[email protected]_relation_modification(p_partition);
527514

528515
SELECT attname, parttype
529516
FROM @[email protected]_config
@@ -610,16 +597,14 @@ BEGIN
610597
v_parent_relid2 := @[email protected]_parent_of_partition(partition2);
611598

612599
/* Acquire data modification locks (prevent further modifications) */
613-
PERFORM @[email protected]_blocking_partitioning_checks(partition1);
614-
PERFORM @[email protected]_relation_modification(partition1);
615-
PERFORM @[email protected]_blocking_partitioning_checks(partition2);
616-
PERFORM @[email protected]_relation_modification(partition2);
600+
PERFORM @[email protected]_relation_modification(partition1);
601+
PERFORM @[email protected]_relation_modification(partition2);
617602

618603
IF v_parent_relid1 != v_parent_relid2 THEN
619604
RAISE EXCEPTION 'Cannot merge partitions with different parents';
620605
END IF;
621606

622-
/* Acquire exclusive lock on parent */
607+
/* Acquire lock on parent */
623608
PERFORM @[email protected]_partitioned_relation(v_parent_relid1);
624609

625610
SELECT attname, parttype
@@ -731,7 +716,7 @@ DECLARE
731716
v_interval TEXT;
732717

733718
BEGIN
734-
/* Acquire exclusive lock on parent */
719+
/* Acquire lock on parent */
735720
PERFORM @[email protected]_partitioned_relation(parent_relid);
736721

737722
SELECT attname, range_interval
@@ -923,7 +908,7 @@ DECLARE
923908
v_part_name TEXT;
924909

925910
BEGIN
926-
/* Acquire exclusive lock on parent */
911+
/* Acquire lock on parent */
927912
PERFORM @[email protected]_partitioned_relation(parent_relid);
928913

929914
IF p_start_value >= p_end_value THEN
@@ -964,7 +949,7 @@ BEGIN
964949
parent_relid := @[email protected]_parent_of_partition(p_partition);
965950
part_name := p_partition::TEXT; /* save the name to be returned */
966951

967-
/* Acquire exclusive lock on parent */
952+
/* Acquire lock on parent */
968953
PERFORM @[email protected]_partitioned_relation(parent_relid);
969954

970955
/* Drop table */
@@ -994,7 +979,7 @@ DECLARE
994979
rel_persistence CHAR;
995980

996981
BEGIN
997-
/* Acquire exclusive lock on parent */
982+
/* Acquire lock on parent */
998983
PERFORM @[email protected]_partitioned_relation(parent_relid);
999984

1000985
/* Ignore temporary tables */
@@ -1054,7 +1039,7 @@ DECLARE
10541039
BEGIN
10551040
parent_relid = @[email protected]_parent_of_partition(p_partition);
10561041

1057-
/* Acquire exclusive lock on parent */
1042+
/* Acquire lock on parent */
10581043
PERFORM @[email protected]_partitioned_relation(parent_relid);
10591044

10601045
v_attname := attname

Diff for: src/pl_funcs.c

+16-16
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ PG_FUNCTION_INFO_V1( is_attribute_nullable );
5353
PG_FUNCTION_INFO_V1( add_to_pathman_config );
5454
PG_FUNCTION_INFO_V1( invalidate_relcache );
5555
PG_FUNCTION_INFO_V1( lock_partitioned_relation );
56-
PG_FUNCTION_INFO_V1( lock_relation_modification );
57-
PG_FUNCTION_INFO_V1( common_blocking_partitioning_checks );
56+
PG_FUNCTION_INFO_V1( prevent_relation_modification );
5857
PG_FUNCTION_INFO_V1( debug_capture );
5958

6059

@@ -698,33 +697,34 @@ lock_partitioned_relation(PG_FUNCTION_ARGS)
698697
Oid relid = PG_GETARG_OID(0);
699698

700699
/* Lock partitioned relation till transaction's end */
701-
xact_lock_partitioned_rel(relid);
702-
703-
PG_RETURN_VOID();
704-
}
705-
706-
Datum
707-
lock_relation_modification(PG_FUNCTION_ARGS)
708-
{
709-
Oid relid = PG_GETARG_OID(0);
710-
711-
/* Lock partitioned relation till transaction's end */
712-
xact_lock_rel_data(relid);
700+
xact_lock_partitioned_rel(relid, false);
713701

714702
PG_RETURN_VOID();
715703
}
716704

705+
/*
706+
* Lock relation exclusively & check for current isolation level.
707+
*/
717708
Datum
718-
common_blocking_partitioning_checks(PG_FUNCTION_ARGS)
709+
prevent_relation_modification(PG_FUNCTION_ARGS)
719710
{
720711
Oid relid = PG_GETARG_OID(0);
721712

713+
/*
714+
* Check that isolation level is READ COMMITTED.
715+
* Else we won't be able to see new rows
716+
* which could slip through locks.
717+
*/
722718
if (!xact_is_level_read_committed())
723719
ereport(ERROR,
724720
(errmsg("Cannot perform blocking partitioning operation"),
725721
errdetail("Expected READ COMMITTED isolation level")));
726722

727-
if (xact_is_table_being_modified(relid))
723+
/*
724+
* Check if table is being modified
725+
* concurrently in a separate transaction.
726+
*/
727+
if (!xact_lock_rel_exclusive(relid, true))
728728
ereport(ERROR,
729729
(errmsg("Cannot perform blocking partitioning operation"),
730730
errdetail("Table \"%s\" is being modified concurrently",

Diff for: src/relation_info.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ get_pathman_relation_info_after_lock(Oid relid, bool unlock_if_not_found)
265265
const PartRelationInfo *prel;
266266

267267
/* Restrict concurrent partition creation (it's dangerous) */
268-
xact_lock_partitioned_rel(relid);
268+
xact_lock_partitioned_rel(relid, false);
269269

270270
prel = get_pathman_relation_info(relid);
271271
if (!prel && unlock_if_not_found)

Diff for: src/xact_handling.c

+28-30
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,19 @@ static inline bool do_we_hold_the_lock(Oid relid, LOCKMODE lockmode);
2424
/*
2525
* Lock certain partitioned relation to disable concurrent access.
2626
*/
27-
void
28-
xact_lock_partitioned_rel(Oid relid)
27+
bool
28+
xact_lock_partitioned_rel(Oid relid, bool nowait)
2929
{
30-
/* Share exclusive lock conflicts with itself */
31-
LockRelationOid(relid, ShareUpdateExclusiveLock);
30+
if (nowait)
31+
{
32+
if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
33+
return true;
34+
return false;
35+
}
36+
else
37+
LockRelationOid(relid, ShareUpdateExclusiveLock);
38+
39+
return true;
3240
}
3341

3442
/*
@@ -41,21 +49,30 @@ xact_unlock_partitioned_rel(Oid relid)
4149
}
4250

4351
/*
44-
* Lock certain relation's data (INSERT | UPDATE | DELETE).
52+
* Lock relation exclusively (SELECTs are possible).
4553
*/
46-
void
47-
xact_lock_rel_data(Oid relid)
54+
bool
55+
xact_lock_rel_exclusive(Oid relid, bool nowait)
4856
{
49-
LockRelationOid(relid, ShareLock);
57+
if (nowait)
58+
{
59+
if (ConditionalLockRelationOid(relid, ExclusiveLock))
60+
return true;
61+
return false;
62+
}
63+
else
64+
LockRelationOid(relid, ExclusiveLock);
65+
66+
return true;
5067
}
5168

5269
/*
53-
* Unlock relation's data.
70+
* Unlock relation (exclusive lock).
5471
*/
5572
void
56-
xact_unlock_rel_data(Oid relid)
73+
xact_unlock_rel_exclusive(Oid relid)
5774
{
58-
UnlockRelationOid(relid, ShareLock);
75+
UnlockRelationOid(relid, ExclusiveLock);
5976
}
6077

6178
/*
@@ -79,25 +96,6 @@ xact_bgw_conflicting_lock_exists(Oid relid)
7996
return false;
8097
}
8198

82-
/*
83-
* Check if table is being modified
84-
* concurrently in a separate transaction.
85-
*/
86-
bool
87-
xact_is_table_being_modified(Oid relid)
88-
{
89-
/*
90-
* Check if someone has already started a
91-
* transaction and modified table's contents.
92-
*/
93-
if (ConditionalLockRelationOid(relid, ExclusiveLock))
94-
{
95-
UnlockRelationOid(relid, ExclusiveLock);
96-
return false;
97-
}
98-
99-
return true;
100-
}
10199

102100
/*
103101
* Check if current transaction's level is READ COMMITTED.

Diff for: src/xact_handling.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,16 @@
1717
/*
1818
* Transaction locks.
1919
*/
20-
void xact_lock_partitioned_rel(Oid relid);
20+
bool xact_lock_partitioned_rel(Oid relid, bool nowait);
2121
void xact_unlock_partitioned_rel(Oid relid);
2222

23-
void xact_lock_rel_data(Oid relid);
24-
void xact_unlock_rel_data(Oid relid);
23+
bool xact_lock_rel_exclusive(Oid relid, bool nowait);
24+
void xact_unlock_rel_exclusive(Oid relid);
2525

2626
/*
2727
* Utility checks.
2828
*/
2929
bool xact_bgw_conflicting_lock_exists(Oid relid);
30-
bool xact_is_table_being_modified(Oid relid);
3130
bool xact_is_level_read_committed(void);
3231

3332
#endif

0 commit comments

Comments
 (0)