Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 04a4760

Browse files
committed
Make walsenders show their replication commands in pg_stat_activity.
A walsender process that has executed a SQL command left the text of that command in pg_stat_activity.query indefinitely, which is quite confusing if it's in RUNNING state but not doing that query. An easy and useful fix is to treat replication commands as if they were SQL queries, and show them in pg_stat_activity according to the same rules as for regular queries. While we're at it, it seems also sensible to set debug_query_string, allowing error logging and debugging to see the replication command. While here, clean up assorted silliness in exec_replication_command: * Clean up SQLCmd code path, and fix its only-accidentally-not-buggy memory management. * Remove useless duplicate call of SnapBuildClearExportedSnapshot(). * replication_scanner_finish() was never called. Back-patch of commit f560209 into v10-v13. I'd originally felt that this didn't merit back-patching, but subsequent confusion while debugging walsender problems suggests that it'll be useful. Also, the original commit has now aged long enough to provide some comfort that it won't cause problems. Discussion: https://postgr.es/m/2673480.1624557299@sss.pgh.pa.us Discussion: https://postgr.es/m/880181.1600026471@sss.pgh.pa.us
1 parent 79c24a0 commit 04a4760

File tree

1 file changed

+36
-30
lines changed

1 file changed

+36
-30
lines changed

src/backend/replication/walsender.c

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,9 @@ exec_replication_command(const char *cmd_string)
14631463

14641464
CHECK_FOR_INTERRUPTS();
14651465

1466+
/*
1467+
* Parse the command.
1468+
*/
14661469
cmd_context = AllocSetContextCreate(CurrentMemoryContext,
14671470
"Replication command context",
14681471
ALLOCSET_DEFAULT_SIZES);
@@ -1473,33 +1476,49 @@ exec_replication_command(const char *cmd_string)
14731476
if (parse_rc != 0)
14741477
ereport(ERROR,
14751478
(errcode(ERRCODE_SYNTAX_ERROR),
1476-
(errmsg_internal("replication command parser returned %d",
1477-
parse_rc))));
1479+
errmsg_internal("replication command parser returned %d",
1480+
parse_rc)));
1481+
replication_scanner_finish();
14781482

14791483
cmd_node = replication_parse_result;
14801484

14811485
/*
1482-
* Log replication command if log_replication_commands is enabled. Even
1483-
* when it's disabled, log the command with DEBUG1 level for backward
1484-
* compatibility. Note that SQL commands are not logged here, and will be
1485-
* logged later if log_statement is enabled.
1486+
* If it's a SQL command, just clean up our mess and return false; the
1487+
* caller will take care of executing it.
14861488
*/
1487-
if (cmd_node->type != T_SQLCmd)
1488-
ereport(log_replication_commands ? LOG : DEBUG1,
1489-
(errmsg("received replication command: %s", cmd_string)));
1489+
if (IsA(cmd_node, SQLCmd))
1490+
{
1491+
if (MyDatabaseId == InvalidOid)
1492+
ereport(ERROR,
1493+
(errmsg("cannot execute SQL commands in WAL sender for physical replication")));
1494+
1495+
MemoryContextSwitchTo(old_context);
1496+
MemoryContextDelete(cmd_context);
1497+
1498+
/* Tell the caller that this wasn't a WalSender command. */
1499+
return false;
1500+
}
14901501

14911502
/*
1492-
* CREATE_REPLICATION_SLOT ... LOGICAL exports a snapshot. If it was
1493-
* called outside of transaction the snapshot should be cleared here.
1503+
* Report query to various monitoring facilities. For this purpose, we
1504+
* report replication commands just like SQL commands.
14941505
*/
1495-
if (!IsTransactionBlock())
1496-
SnapBuildClearExportedSnapshot();
1506+
debug_query_string = cmd_string;
1507+
1508+
pgstat_report_activity(STATE_RUNNING, cmd_string);
14971509

14981510
/*
1499-
* For aborted transactions, don't allow anything except pure SQL, the
1500-
* exec_simple_query() will handle it correctly.
1511+
* Log replication command if log_replication_commands is enabled. Even
1512+
* when it's disabled, log the command with DEBUG1 level for backward
1513+
* compatibility.
15011514
*/
1502-
if (IsAbortedTransactionBlockState() && !IsA(cmd_node, SQLCmd))
1515+
ereport(log_replication_commands ? LOG : DEBUG1,
1516+
(errmsg("received replication command: %s", cmd_string)));
1517+
1518+
/*
1519+
* Disallow replication commands in aborted transaction blocks.
1520+
*/
1521+
if (IsAbortedTransactionBlockState())
15031522
ereport(ERROR,
15041523
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
15051524
errmsg("current transaction is aborted, "
@@ -1515,9 +1534,6 @@ exec_replication_command(const char *cmd_string)
15151534
initStringInfo(&reply_message);
15161535
initStringInfo(&tmpbuf);
15171536

1518-
/* Report to pgstat that this process is running */
1519-
pgstat_report_activity(STATE_RUNNING, NULL);
1520-
15211537
switch (cmd_node->type)
15221538
{
15231539
case T_IdentifySystemCmd:
@@ -1567,17 +1583,6 @@ exec_replication_command(const char *cmd_string)
15671583
}
15681584
break;
15691585

1570-
case T_SQLCmd:
1571-
if (MyDatabaseId == InvalidOid)
1572-
ereport(ERROR,
1573-
(errmsg("cannot execute SQL commands in WAL sender for physical replication")));
1574-
1575-
/* Report to pgstat that this process is now idle */
1576-
pgstat_report_activity(STATE_IDLE, NULL);
1577-
1578-
/* Tell the caller that this wasn't a WalSender command. */
1579-
return false;
1580-
15811586
default:
15821587
elog(ERROR, "unrecognized replication command node tag: %u",
15831588
cmd_node->type);
@@ -1592,6 +1597,7 @@ exec_replication_command(const char *cmd_string)
15921597

15931598
/* Report to pgstat that this process is now idle */
15941599
pgstat_report_activity(STATE_IDLE, NULL);
1600+
debug_query_string = NULL;
15951601

15961602
return true;
15971603
}

0 commit comments

Comments
 (0)