Skip to content

Commit 25f4d62

Browse files
committed
[#29115] YSQL: Add PG backend type for auto analyze
Summary: Auto Analyze service periodically starts a local PG connection and runs ANALYZEs in the background. Concurrent CREATE INDEX can time out waiting for the postgres backend used by auto analyze to catch up the latest catalog version because of long-running ANALYZE command. On the happy path, concurrent DDL can abort auto-ANALYZE. However, it was discovered that a ANALYZE request with a large size of ybctids can exceed the read buffer memory limit causing ANALYZE execution to hang. Since ANALYZE doesn't write to user tables and only writes to system catalogs (pg_class, pg_statistic, etc), it is safe to let CREATE INDEX ignore the backend used by auto-ANALYZE. To achieve this goal, this diff adds one PG backend type `YB_AUTO_ANALYZE_BACKEND` specific for auto analyze to use. A libpq option: `yb_auto_analyze` is added accordingly. This option can only be used by tserver to postgres libpq connection with yb-tserver-key authentication. Jira: DB-18884 Test Plan: ./yb_build.sh --cxx-test pgwrapper_pg_auto_analyze-test --gtest_filter PgConcurrentCreateIndexTest.ConcurrentCreateIndex Reviewers: sanketh, jason, smishra, pjain Reviewed By: jason Subscribers: ybase, svc_phabricator, jason, yql Differential Revision: https://phorge.dev.yugabyte.com/D47906
1 parent f5669fe commit 25f4d62

File tree

19 files changed

+122
-7
lines changed

19 files changed

+122
-7
lines changed

src/postgres/contrib/postgres_fdw/expected/yb.port.postgres_fdw.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9906,7 +9906,7 @@ DO $d$
99069906
END;
99079907
$d$;
99089908
ERROR: invalid option "password"
9909-
HINT: Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, sslcrldir, sslsni, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, truncatable, fetch_size, batch_size, async_capable, parallel_commit, keep_connections, server_type
9909+
HINT: Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, sslcrldir, sslsni, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, yb_auto_analyze, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, truncatable, fetch_size, batch_size, async_capable, parallel_commit, keep_connections, server_type
99109910
CONTEXT: SQL statement "ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw')"
99119911
PL/pgSQL function inline_code_block line 3 at EXECUTE
99129912
-- If we add a password for our user mapping instead, we should get a different

src/postgres/src/backend/commands/indexcmds.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5151,6 +5151,7 @@ YbWaitForBackendsCatalogVersion()
51515151
" pg_stat_activity WHERE"
51525152
" backend_type != 'walsender' AND"
51535153
" backend_type != 'yb-conn-mgr walsender' AND"
5154+
" backend_type != 'yb auto analyze backend' AND"
51545155
" catalog_version < %" PRIu64
51555156
" AND datid = %u;",
51565157
catalog_version,

src/postgres/src/backend/libpq/auth.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,18 @@ ClientAuthentication(Port *port)
460460

461461
CHECK_FOR_INTERRUPTS();
462462

463+
/*
464+
* Only tserver-owned backends using yb-tserver-key authentication are
465+
* allowed to run as yb_auto_analyze.
466+
*/
467+
if (IsYugaByteEnabled() && MyBackendType == YB_AUTO_ANALYZE_BACKEND &&
468+
port->hba->auth_method != uaYbTserverKey &&
469+
!YBCGetGFlags()->TEST_ysql_bypass_auto_analyze_auth_check)
470+
ereport(FATAL,
471+
(errcode(ERRCODE_PROTOCOL_VIOLATION),
472+
errmsg("yb_auto_analyze can only be set if the authentication method "
473+
"is yb-tserver-key")));
474+
463475
/*
464476
* This is the first point where we have access to the hba record for the
465477
* current connection, so perform any verifications based on the hba

src/postgres/src/backend/postmaster/postmaster.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,6 +2129,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
21292129
char *yb_auth_backend_remote_host = NULL;
21302130
char yb_logical_conn_type = 'U'; /* Unencrypted */
21312131
bool yb_logical_conn_type_provided = false;
2132+
bool yb_auto_analyze_backend = false;
21322133

21332134
pq_startmsgread();
21342135

@@ -2426,6 +2427,17 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
24262427
yb_logical_conn_type = *pstrdup(valptr);
24272428
yb_logical_conn_type_provided = true;
24282429
}
2430+
else if (YBIsEnabledInPostgresEnvVar()
2431+
&& strcmp(nameptr, "yb_auto_analyze") == 0)
2432+
{
2433+
if (!parse_bool(valptr, &yb_auto_analyze_backend))
2434+
ereport(FATAL,
2435+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2436+
errmsg("invalid value for parameter \"%s\": \"%s\"",
2437+
"yb_auto_analyze",
2438+
valptr),
2439+
errhint("Valid values are: \"false\", 0, \"true\", 1.")));
2440+
}
24292441
else if (strncmp(nameptr, "_pq_.", 5) == 0)
24302442
{
24312443
/*
@@ -2559,6 +2571,8 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
25592571

25602572
if (am_walsender)
25612573
MyBackendType = B_WAL_SENDER;
2574+
else if (yb_auto_analyze_backend)
2575+
MyBackendType = YB_AUTO_ANALYZE_BACKEND;
25622576
else
25632577
MyBackendType = B_BACKEND;
25642578

src/postgres/src/backend/utils/activity/backend_status.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ pgstat_bestart(void)
377377
/* YB: Increment the total connections counter */
378378
if (lbeentry.st_procpid > 0 &&
379379
(lbeentry.st_backendType == B_BACKEND ||
380+
lbeentry.st_backendType == YB_AUTO_ANALYZE_BACKEND ||
380381
lbeentry.st_backendType == YB_YSQL_CONN_MGR))
381382
(*yb_new_conn)++;
382383

@@ -399,6 +400,7 @@ pgstat_bestart(void)
399400
if (lbeentry.st_backendType == B_BACKEND
400401
|| lbeentry.st_backendType == B_WAL_SENDER
401402
|| lbeentry.st_backendType == B_BG_WORKER
403+
|| lbeentry.st_backendType == YB_AUTO_ANALYZE_BACKEND
402404
|| lbeentry.st_backendType == YB_YSQL_CONN_MGR
403405
|| lbeentry.st_backendType == YB_YSQL_CONN_MGR_WAL_SENDER)
404406
lbeentry.st_userid = GetSessionUserId();

src/postgres/src/backend/utils/adt/pgstatfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
805805
proc = BackendPidGetProc(beentry->st_procpid);
806806

807807
if (proc == NULL && (beentry->st_backendType != B_BACKEND &&
808+
beentry->st_backendType != YB_AUTO_ANALYZE_BACKEND &&
808809
beentry->st_backendType != YB_YSQL_CONN_MGR))
809810
{
810811
/*

src/postgres/src/backend/utils/init/miscinit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ GetBackendTypeDesc(BackendType backendType)
301301
break;
302302
case YB_YSQL_CONN_MGR_WAL_SENDER:
303303
backendDesc = "yb-conn-mgr walsender";
304+
break;
305+
case YB_AUTO_ANALYZE_BACKEND:
306+
backendDesc = "yb auto analyze backend";
304307
}
305308

306309
return backendDesc;

src/postgres/src/include/miscadmin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ typedef enum BackendType
361361
B_LOGGER,
362362
YB_YSQL_CONN_MGR,
363363
YB_YSQL_CONN_MGR_WAL_SENDER,
364+
YB_AUTO_ANALYZE_BACKEND,
364365
} BackendType;
365366

366367
extern PGDLLIMPORT BackendType MyBackendType;

src/postgres/src/interfaces/libpq/fe-connect.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
345345
"Target-Session-Attrs", "", 15, /* sizeof("prefer-standby") = 15 */
346346
offsetof(struct pg_conn, target_session_attrs)},
347347

348+
{"yb_auto_analyze", NULL, NULL, NULL,
349+
"YB-Auto-Analyze", "", 6, /* sizeof("false") = 6 */
350+
offsetof(struct pg_conn, yb_auto_analyze)},
351+
348352
/* Terminating entry --- MUST BE LAST */
349353
{NULL, NULL, NULL, NULL,
350354
NULL, NULL, 0}
@@ -4181,6 +4185,8 @@ freePGconn(PGconn *conn)
41814185
free(conn->rowBuf);
41824186
if (conn->target_session_attrs)
41834187
free(conn->target_session_attrs);
4188+
if (conn->yb_auto_analyze)
4189+
free(conn->yb_auto_analyze);
41844190
termPQExpBuffer(&conn->errorMessage);
41854191
termPQExpBuffer(&conn->workBuffer);
41864192

src/postgres/src/interfaces/libpq/fe-protocol3.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,6 +2236,8 @@ build_startup_packet(const PGconn *conn, char *packet,
22362236
ADD_STARTUP_OPTION("replication", conn->replication);
22372237
if (conn->pgoptions && conn->pgoptions[0])
22382238
ADD_STARTUP_OPTION("options", conn->pgoptions);
2239+
if (conn->yb_auto_analyze && conn->yb_auto_analyze[0])
2240+
ADD_STARTUP_OPTION("yb_auto_analyze", conn->yb_auto_analyze);
22392241
if (conn->send_appname)
22402242
{
22412243
/* Use appname if present, otherwise use fallback */

0 commit comments

Comments
 (0)