mirror of
https://github.com/neondatabase/neon.git
synced 2025-12-22 21:59:59 +00:00
Do not allocate anything in subtransaction memory context (#12176)
## Problem See https://github.com/neondatabase/neon/issues/12173 ## Summary of changes Allocate table in TopTransactionMemoryContext --------- Co-authored-by: Konstantin Knizhnik <knizhnik@neon.tech>
This commit is contained in:
committed by
GitHub
parent
cc699f6f85
commit
436a117c15
@@ -98,12 +98,14 @@ typedef struct
|
||||
typedef struct DdlHashTable
|
||||
{
|
||||
struct DdlHashTable *prev_table;
|
||||
size_t subtrans_level;
|
||||
HTAB *db_table;
|
||||
HTAB *role_table;
|
||||
} DdlHashTable;
|
||||
|
||||
static DdlHashTable RootTable;
|
||||
static DdlHashTable *CurrentDdlTable = &RootTable;
|
||||
static int SubtransLevel; /* current nesting level of subtransactions */
|
||||
|
||||
static void
|
||||
PushKeyValue(JsonbParseState **state, char *key, char *value)
|
||||
@@ -332,9 +334,25 @@ SendDeltasToControlPlane()
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InitCurrentDdlTableIfNeeded()
|
||||
{
|
||||
/* Lazy construction of DllHashTable chain */
|
||||
if (SubtransLevel > CurrentDdlTable->subtrans_level)
|
||||
{
|
||||
DdlHashTable *new_table = MemoryContextAlloc(CurTransactionContext, sizeof(DdlHashTable));
|
||||
new_table->prev_table = CurrentDdlTable;
|
||||
new_table->subtrans_level = SubtransLevel;
|
||||
new_table->role_table = NULL;
|
||||
new_table->db_table = NULL;
|
||||
CurrentDdlTable = new_table;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InitDbTableIfNeeded()
|
||||
{
|
||||
InitCurrentDdlTableIfNeeded();
|
||||
if (!CurrentDdlTable->db_table)
|
||||
{
|
||||
HASHCTL db_ctl = {};
|
||||
@@ -353,6 +371,7 @@ InitDbTableIfNeeded()
|
||||
static void
|
||||
InitRoleTableIfNeeded()
|
||||
{
|
||||
InitCurrentDdlTableIfNeeded();
|
||||
if (!CurrentDdlTable->role_table)
|
||||
{
|
||||
HASHCTL role_ctl = {};
|
||||
@@ -371,19 +390,21 @@ InitRoleTableIfNeeded()
|
||||
static void
|
||||
PushTable()
|
||||
{
|
||||
DdlHashTable *new_table = MemoryContextAlloc(CurTransactionContext, sizeof(DdlHashTable));
|
||||
|
||||
new_table->prev_table = CurrentDdlTable;
|
||||
new_table->role_table = NULL;
|
||||
new_table->db_table = NULL;
|
||||
CurrentDdlTable = new_table;
|
||||
SubtransLevel += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
MergeTable()
|
||||
{
|
||||
DdlHashTable *old_table = CurrentDdlTable;
|
||||
DdlHashTable *old_table;
|
||||
|
||||
Assert(SubtransLevel >= CurrentDdlTable->subtrans_level);
|
||||
if (--SubtransLevel >= CurrentDdlTable->subtrans_level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
old_table = CurrentDdlTable;
|
||||
CurrentDdlTable = old_table->prev_table;
|
||||
|
||||
if (old_table->db_table)
|
||||
@@ -476,11 +497,15 @@ MergeTable()
|
||||
static void
|
||||
PopTable()
|
||||
{
|
||||
/*
|
||||
* Current table gets freed because it is allocated in aborted
|
||||
* subtransaction's memory context.
|
||||
*/
|
||||
CurrentDdlTable = CurrentDdlTable->prev_table;
|
||||
Assert(SubtransLevel >= CurrentDdlTable->subtrans_level);
|
||||
if (--SubtransLevel < CurrentDdlTable->subtrans_level)
|
||||
{
|
||||
/*
|
||||
* Current table gets freed because it is allocated in aborted
|
||||
* subtransaction's memory context.
|
||||
*/
|
||||
CurrentDdlTable = CurrentDdlTable->prev_table;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
21
test_runner/sql_regress/expected/neon-subxacts.out
Normal file
21
test_runner/sql_regress/expected/neon-subxacts.out
Normal file
@@ -0,0 +1,21 @@
|
||||
DO $$
|
||||
DECLARE
|
||||
i numeric;
|
||||
BEGIN
|
||||
create role somebody;
|
||||
FOR i IN 1..1000000 LOOP
|
||||
BEGIN
|
||||
IF i % 1000 = 0 THEN
|
||||
alter role somebody password 'welcome';
|
||||
ELSE
|
||||
PERFORM 1;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'error';
|
||||
END;
|
||||
IF I = 1000000 THEN
|
||||
PERFORM pg_log_backend_memory_contexts(pg_backend_pid());
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
@@ -10,3 +10,4 @@ test: neon-clog
|
||||
test: neon-test-utils
|
||||
test: neon-vacuum-full
|
||||
test: neon-event-triggers
|
||||
test: neon-subxacts
|
||||
|
||||
21
test_runner/sql_regress/sql/neon-subxacts.sql
Normal file
21
test_runner/sql_regress/sql/neon-subxacts.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
DO $$
|
||||
DECLARE
|
||||
i numeric;
|
||||
BEGIN
|
||||
create role somebody;
|
||||
FOR i IN 1..1000000 LOOP
|
||||
BEGIN
|
||||
IF i % 1000 = 0 THEN
|
||||
alter role somebody password 'welcome';
|
||||
ELSE
|
||||
PERFORM 1;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'error';
|
||||
END;
|
||||
IF I = 1000000 THEN
|
||||
PERFORM pg_log_backend_memory_contexts(pg_backend_pid());
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
Reference in New Issue
Block a user