diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 588c1ec536..6bfd5474e2 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1373,8 +1373,9 @@ ExecuteTruncate(TruncateStmt *stmt)
 		Relation	rel;
 		bool		recurse = rv->inh;
 		Oid			myrelid;
+		LOCKMODE	lockmode = AccessExclusiveLock;
 
-		myrelid = RangeVarGetRelidExtended(rv, AccessExclusiveLock,
+		myrelid = RangeVarGetRelidExtended(rv, lockmode,
 										   0, RangeVarCallbackForTruncate,
 										   NULL);
 
@@ -1384,7 +1385,7 @@ ExecuteTruncate(TruncateStmt *stmt)
 		/* don't throw error for "TRUNCATE foo, foo" */
 		if (list_member_oid(relids, myrelid))
 		{
-			heap_close(rel, AccessExclusiveLock);
+			heap_close(rel, lockmode);
 			continue;
 		}
 
@@ -1405,7 +1406,7 @@ ExecuteTruncate(TruncateStmt *stmt)
 			ListCell   *child;
 			List	   *children;
 
-			children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL);
+			children = find_all_inheritors(myrelid, lockmode, NULL);
 
 			foreach(child, children)
 			{
@@ -1416,6 +1417,21 @@ ExecuteTruncate(TruncateStmt *stmt)
 
 				/* find_all_inheritors already got lock */
 				rel = heap_open(childrelid, NoLock);
+
+				/*
+				 * It is possible that the parent table has children that are
+				 * temp tables of other backends.  We cannot safely access
+				 * such tables (because of buffering issues), and the best
+				 * thing to do is to silently ignore them.  Note that this
+				 * check overlaps with truncate_check_activity()'s inner checks
+				 * done below, but an extra one is kept here for simplicity.
+				 */
+				if (RELATION_IS_OTHER_TEMP(rel))
+				{
+					heap_close(rel, lockmode);
+					continue;
+				}
+
 				truncate_check_rel(RelationGetRelid(rel), rel->rd_rel);
 				truncate_check_activity(rel);
 
diff --git a/src/test/isolation/expected/inherit-temp.out b/src/test/isolation/expected/inherit-temp.out
new file mode 100644
index 0000000000..eabfa07b48
--- /dev/null
+++ b/src/test/isolation/expected/inherit-temp.out
@@ -0,0 +1,217 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_select_p s1_select_c s2_select_p s2_select_c
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+2              
+3              
+4              
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+3              
+4              
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+2              
+5              
+6              
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+5              
+6              
+
+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
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s1_update_p: UPDATE inh_temp_parent SET a = 11 WHERE a = 1;
+step s1_update_c: UPDATE inh_temp_parent SET a = 13 WHERE a = 3;
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+2              
+11             
+4              
+13             
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+4              
+13             
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+2              
+11             
+5              
+6              
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+5              
+6              
+
+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
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s2_update_c: UPDATE inh_temp_parent SET a = 15 WHERE a = 5;
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+2              
+3              
+4              
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+3              
+4              
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+2              
+6              
+15             
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+6              
+15             
+
+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
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s1_delete_p: DELETE FROM inh_temp_parent WHERE a = 2;
+step s1_delete_c: DELETE FROM inh_temp_parent WHERE a = 4;
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+3              
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+3              
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+5              
+6              
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+5              
+6              
+
+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
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s2_delete_c: DELETE FROM inh_temp_parent WHERE a = 5;
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+2              
+3              
+4              
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+3              
+4              
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+1              
+2              
+6              
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+6              
+
+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
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s1_truncate_p: TRUNCATE inh_temp_parent;
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+5              
+6              
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+5              
+6              
+
+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
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s2_truncate_p: TRUNCATE inh_temp_parent;
+step s1_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+3              
+4              
+step s1_select_c: SELECT a FROM inh_temp_s1;
+a              
+
+3              
+4              
+step s2_select_p: SELECT a FROM inh_temp_parent;
+a              
+
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+
+starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_begin s1_truncate_p s2_select_p s1_commit
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s1_begin: BEGIN;
+step s1_truncate_p: TRUNCATE inh_temp_parent;
+step s2_select_p: SELECT a FROM inh_temp_parent; <waiting ...>
+step s1_commit: COMMIT;
+step s2_select_p: <... completed>
+a              
+
+5              
+6              
+
+starting permutation: s1_insert_p s1_insert_c s2_insert_c s1_begin s1_truncate_p s2_select_c s1_commit
+step s1_insert_p: INSERT INTO inh_temp_parent VALUES (1), (2);
+step s1_insert_c: INSERT INTO inh_temp_s1 VALUES (3), (4);
+step s2_insert_c: INSERT INTO inh_temp_s2 VALUES (5), (6);
+step s1_begin: BEGIN;
+step s1_truncate_p: TRUNCATE inh_temp_parent;
+step s2_select_c: SELECT a FROM inh_temp_s2;
+a              
+
+5              
+6              
+step s1_commit: COMMIT;
diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule
index dd57a96e78..8a9a854e8a 100644
--- a/src/test/isolation/isolation_schedule
+++ b/src/test/isolation/isolation_schedule
@@ -27,6 +27,7 @@ test: fk-deadlock2
 test: eval-plan-qual
 test: lock-update-delete
 test: lock-update-traversal
+test: inherit-temp
 test: insert-conflict-do-nothing
 test: insert-conflict-do-nothing-2
 test: insert-conflict-do-update
diff --git a/src/test/isolation/specs/inherit-temp.spec b/src/test/isolation/specs/inherit-temp.spec
new file mode 100644
index 0000000000..31961be63d
--- /dev/null
+++ b/src/test/isolation/specs/inherit-temp.spec
@@ -0,0 +1,78 @@
+# Tests for inheritance trees with temporary relations
+#
+# Inheritance trees are allowed to mix relations with different persistence
+# as long as a persistent child relation does not try to inherit from a
+# temporary parent.  This checks several scenarios with SELECT, INSERT, UPDATE,
+# DELETE and TRUNCATE.  Any temporary relation inheriting from the same
+# persistent parent should be isolated and handled only in its own session.
+
+setup
+{
+  CREATE TABLE inh_temp_parent (a int);
+}
+
+teardown
+{
+  DROP TABLE inh_temp_parent;
+}
+
+# Session 1 executes actions which act directly on both the parent and
+# its child.  Abbreviation "c" is used for queries working on the child
+# and "p" on the parent.
+session "s1"
+setup
+{
+  CREATE TEMPORARY TABLE inh_temp_s1 () INHERITS (inh_temp_parent);
+}
+step "s1_begin" { BEGIN; }
+step "s1_truncate_p" { TRUNCATE inh_temp_parent; }
+step "s1_select_p" { SELECT a FROM inh_temp_parent; }
+step "s1_select_c" { SELECT a FROM inh_temp_s1; }
+step "s1_insert_p" { INSERT INTO inh_temp_parent VALUES (1), (2); }
+step "s1_insert_c" { INSERT INTO inh_temp_s1 VALUES (3), (4); }
+step "s1_update_p" { UPDATE inh_temp_parent SET a = 11 WHERE a = 1; }
+step "s1_update_c" { UPDATE inh_temp_parent SET a = 13 WHERE a = 3; }
+step "s1_delete_p" { DELETE FROM inh_temp_parent WHERE a = 2; }
+step "s1_delete_c" { DELETE FROM inh_temp_parent WHERE a = 4; }
+step "s1_commit" { COMMIT; }
+teardown
+{
+  DROP TABLE inh_temp_s1;
+}
+
+# Session 2 executes actions on the parent which act only on the child.
+session "s2"
+setup
+{
+  CREATE TEMPORARY TABLE inh_temp_s2 () INHERITS (inh_temp_parent);
+}
+step "s2_truncate_p" { TRUNCATE inh_temp_parent; }
+step "s2_select_p" { SELECT a FROM inh_temp_parent; }
+step "s2_select_c" { SELECT a FROM inh_temp_s2; }
+step "s2_insert_c" { INSERT INTO inh_temp_s2 VALUES (5), (6); }
+step "s2_update_c" { UPDATE inh_temp_parent SET a = 15 WHERE a = 5; }
+step "s2_delete_c" { DELETE FROM inh_temp_parent WHERE a = 5; }
+teardown
+{
+  DROP TABLE inh_temp_s2;
+}
+
+# Check INSERT behavior across sessions
+permutation "s1_insert_p" "s1_insert_c" "s2_insert_c" "s1_select_p" "s1_select_c" "s2_select_p" "s2_select_c"
+
+# Check UPDATE behavior across sessions
+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"
+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"
+
+# Check DELETE behavior across sessions
+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"
+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"
+
+# Check TRUNCATE behavior across sessions
+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"
+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"
+
+# TRUNCATE on a parent tree does not block access to temporary child relation
+# of another session, and blocks when scanning the parent.
+permutation "s1_insert_p" "s1_insert_c" "s2_insert_c" "s1_begin" "s1_truncate_p" "s2_select_p" "s1_commit"
+permutation "s1_insert_p" "s1_insert_c" "s2_insert_c" "s1_begin" "s1_truncate_p" "s2_select_c" "s1_commit"
