Skip to content

Commit f560209

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: * The SQLCmd path failed to restore CurrentMemoryContext to the caller's value, and failed to delete the temp context created in this routine. It's only through great good fortune that these oversights did not result in long-term memory leaks or other problems. It seems cleaner to code SQLCmd as a separate early-exit path, so do it like that. * Remove useless duplicate call of SnapBuildClearExportedSnapshot(). * replication_scanner_finish() was never called. None of those things are significant enough to merit a backpatch, so this is for HEAD only. Discussion: https://postgr.es/m/880181.1600026471@sss.pgh.pa.us
1 parent 47a3a1c commit f560209

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

src/backend/replication/walsender.c

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,9 @@ exec_replication_command(const char *cmd_string)
15451545

15461546
CHECK_FOR_INTERRUPTS();
15471547

1548+
/*
1549+
* Parse the command.
1550+
*/
15481551
cmd_context = AllocSetContextCreate(CurrentMemoryContext,
15491552
"Replication command context",
15501553
ALLOCSET_DEFAULT_SIZES);
@@ -1557,31 +1560,47 @@ exec_replication_command(const char *cmd_string)
15571560
(errcode(ERRCODE_SYNTAX_ERROR),
15581561
errmsg_internal("replication command parser returned %d",
15591562
parse_rc)));
1563+
replication_scanner_finish();
15601564

15611565
cmd_node = replication_parse_result;
15621566

15631567
/*
1564-
* Log replication command if log_replication_commands is enabled. Even
1565-
* when it's disabled, log the command with DEBUG1 level for backward
1566-
* compatibility. Note that SQL commands are not logged here, and will be
1567-
* logged later if log_statement is enabled.
1568+
* If it's a SQL command, just clean up our mess and return false; the
1569+
* caller will take care of executing it.
15681570
*/
1569-
if (cmd_node->type != T_SQLCmd)
1570-
ereport(log_replication_commands ? LOG : DEBUG1,
1571-
(errmsg("received replication command: %s", cmd_string)));
1571+
if (IsA(cmd_node, SQLCmd))
1572+
{
1573+
if (MyDatabaseId == InvalidOid)
1574+
ereport(ERROR,
1575+
(errmsg("cannot execute SQL commands in WAL sender for physical replication")));
1576+
1577+
MemoryContextSwitchTo(old_context);
1578+
MemoryContextDelete(cmd_context);
1579+
1580+
/* Tell the caller that this wasn't a WalSender command. */
1581+
return false;
1582+
}
15721583

15731584
/*
1574-
* CREATE_REPLICATION_SLOT ... LOGICAL exports a snapshot. If it was
1575-
* called outside of transaction the snapshot should be cleared here.
1585+
* Report query to various monitoring facilities. For this purpose, we
1586+
* report replication commands just like SQL commands.
15761587
*/
1577-
if (!IsTransactionBlock())
1578-
SnapBuildClearExportedSnapshot();
1588+
debug_query_string = cmd_string;
1589+
1590+
pgstat_report_activity(STATE_RUNNING, cmd_string);
15791591

15801592
/*
1581-
* For aborted transactions, don't allow anything except pure SQL, the
1582-
* exec_simple_query() will handle it correctly.
1593+
* Log replication command if log_replication_commands is enabled. Even
1594+
* when it's disabled, log the command with DEBUG1 level for backward
1595+
* compatibility.
15831596
*/
1584-
if (IsAbortedTransactionBlockState() && !IsA(cmd_node, SQLCmd))
1597+
ereport(log_replication_commands ? LOG : DEBUG1,
1598+
(errmsg("received replication command: %s", cmd_string)));
1599+
1600+
/*
1601+
* Disallow replication commands in aborted transaction blocks.
1602+
*/
1603+
if (IsAbortedTransactionBlockState())
15851604
ereport(ERROR,
15861605
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
15871606
errmsg("current transaction is aborted, "
@@ -1597,9 +1616,6 @@ exec_replication_command(const char *cmd_string)
15971616
initStringInfo(&reply_message);
15981617
initStringInfo(&tmpbuf);
15991618

1600-
/* Report to pgstat that this process is running */
1601-
pgstat_report_activity(STATE_RUNNING, NULL);
1602-
16031619
switch (cmd_node->type)
16041620
{
16051621
case T_IdentifySystemCmd:
@@ -1651,17 +1667,6 @@ exec_replication_command(const char *cmd_string)
16511667
}
16521668
break;
16531669

1654-
case T_SQLCmd:
1655-
if (MyDatabaseId == InvalidOid)
1656-
ereport(ERROR,
1657-
(errmsg("cannot execute SQL commands in WAL sender for physical replication")));
1658-
1659-
/* Report to pgstat that this process is now idle */
1660-
pgstat_report_activity(STATE_IDLE, NULL);
1661-
1662-
/* Tell the caller that this wasn't a WalSender command. */
1663-
return false;
1664-
16651670
default:
16661671
elog(ERROR, "unrecognized replication command node tag: %u",
16671672
cmd_node->type);
@@ -1677,6 +1682,7 @@ exec_replication_command(const char *cmd_string)
16771682

16781683
/* Report to pgstat that this process is now idle */
16791684
pgstat_report_activity(STATE_IDLE, NULL);
1685+
debug_query_string = NULL;
16801686

16811687
return true;
16821688
}

0 commit comments

Comments
 (0)