On Thu, Dec 26, 2019 at 9:08 AM Guillaume Lelarge <guilla...@lelarge.info> wrote: > > Le mer. 25 déc. 2019 à 19:30, Julien Rouhaud <rjuju...@gmail.com> a écrit : >> >> On Wed, Dec 25, 2019 at 7:03 PM Julien Rouhaud <rjuju...@gmail.com> wrote: >> > >> > Guillaume (in Cc) recently pointed out [1] that it's currently not >> > possible to retrieve the list of parallel workers for a given backend >> > at the SQL level. His use case was to develop a function in plpgsql >> > to sample a given query wait event, but it's not hard to imagine other >> > useful use cases for this information, for instance doing some >> > analysis on the average number of workers per parallel query, or ratio >> > of parallel queries. IIUC parallel queries is for now the only user >> > of lock group, so this should work just fine. >> > >> > I'm attaching a trivial patch to expose the group leader pid if any >> > in pg_stat_activity. Quick example of usage: >> > >> > =# SELECT query, leader_pid, >> > array_agg(pid) filter(WHERE leader_pid != pid) AS members >> > FROM pg_stat_activity >> > WHERE leader_pid IS NOT NULL >> > GROUP BY query, leader_pid; >> > query | leader_pid | members >> > -------------------+------------+--------------- >> > select * from t1; | 28701 | {28728,28732} >> > (1 row) >> > >> > >> > [1] https://twitter.com/g_lelarge/status/1209486212190343168 >> >> And I just realized that I forgot to update rule.out, sorry about >> that. v2 attached. > > > So I tried your patch this morning, and it works really well. > > On a SELECT count(*), I got this: > > SELECT leader_pid, pid, wait_event_type, wait_event, state, backend_type FROM > pg_stat_activity WHERE pid=111439 or leader_pid=111439; > > ┌────────────┬────────┬─────────────────┬──────────────┬────────┬─────────────────┐ > │ leader_pid │ pid │ wait_event_type │ wait_event │ state │ > backend_type │ > ├────────────┼────────┼─────────────────┼──────────────┼────────┼─────────────────┤ > │ 111439 │ 111439 │ LWLock │ WALWriteLock │ active │ client > backend │ > │ 111439 │ 116887 │ LWLock │ WALWriteLock │ active │ parallel > worker │ > │ 111439 │ 116888 │ IO │ WALSync │ active │ parallel > worker │ > └────────────┴────────┴─────────────────┴──────────────┴────────┴─────────────────┘ > (3 rows) > > and this from a CREATE INDEX: > > ┌────────────┬────────┬─────────────────┬────────────┬────────┬─────────────────┐ > │ leader_pid │ pid │ wait_event_type │ wait_event │ state │ backend_type > │ > ├────────────┼────────┼─────────────────┼────────────┼────────┼─────────────────┤ > │ 111439 │ 111439 │ │ │ active │ client > backend │ > │ 111439 │ 118775 │ │ │ active │ parallel > worker │ > └────────────┴────────┴─────────────────┴────────────┴────────┴─────────────────┘ > (2 rows) > > Anyway, it applies cleanly, it compiles, and it works. Documentation is > available. So it looks to me it's good to go :)
Thanks for the review Guillaume. Double checking the doc, I see that I made a copy/pasto mistake in the new field name. Attached v3 should be all good.
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index dcb58115af..a64959b600 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -614,6 +614,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser <entry><type>integer</type></entry> <entry>Process ID of this backend</entry> </row> + <row> + <entry><structfield>leader_pid</structfield></entry> + <entry><type>integer</type></entry> + <entry>Process ID of the lock group leader, if any</entry> + </row> <row> <entry><structfield>usesysid</structfield></entry> <entry><type>oid</type></entry> diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index f7800f01a6..0c3eb08028 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -734,6 +734,7 @@ CREATE VIEW pg_stat_activity AS S.datid AS datid, D.datname AS datname, S.pid, + S.leader_pid, S.usesysid, U.rolname AS usename, S.application_name, diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index d9f78221aa..323eb89c86 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -545,7 +545,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) Datum pg_stat_get_activity(PG_FUNCTION_ARGS) { -#define PG_STAT_GET_ACTIVITY_COLS 29 +#define PG_STAT_GET_ACTIVITY_COLS 30 int num_backends = pgstat_fetch_stat_numbackends(); int curr_backend; int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0); @@ -684,6 +684,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) values[5] = CStringGetTextDatum(clipped_activity); pfree(clipped_activity); + nulls[29] = true; proc = BackendPidGetProc(beentry->st_procpid); if (proc != NULL) { @@ -693,6 +694,12 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) wait_event_type = pgstat_get_wait_event_type(raw_wait_event); wait_event = pgstat_get_wait_event(raw_wait_event); + if (proc->lockGroupLeader) + { + values[29] = Int32GetDatum(proc->lockGroupLeader->pid); + nulls[29] = false; + } + } else if (beentry->st_backendType != B_BACKEND) { diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index ac8f64b219..6ff7322425 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5148,9 +5148,9 @@ proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f', proretset => 't', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => 'int4', - proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text,bool,text,bool}', - proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc}', + proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text,bool,text,bool,int4}', + proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid}', prosrc => 'pg_stat_get_activity' }, { oid => '3318', descr => 'statistics: information about progress of backends running maintenance command', diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 80a07825b9..02200c46c4 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1724,6 +1724,7 @@ pg_shadow| SELECT pg_authid.rolname AS usename, pg_stat_activity| SELECT s.datid, d.datname, s.pid, + s.leader_pid, s.usesysid, u.rolname AS usename, s.application_name, @@ -1741,7 +1742,7 @@ pg_stat_activity| SELECT s.datid, s.backend_xmin, s.query, s.backend_type - FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc) + FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid) LEFT JOIN pg_database d ON ((s.datid = d.oid))) LEFT JOIN pg_authid u ON ((s.usesysid = u.oid))); pg_stat_all_indexes| SELECT c.oid AS relid, @@ -1845,7 +1846,7 @@ pg_stat_gssapi| SELECT s.pid, s.gss_auth AS gss_authenticated, s.gss_princ AS principal, s.gss_enc AS encrypted - FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc) + FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid) WHERE (s.client_port IS NOT NULL); pg_stat_progress_cluster| SELECT s.pid, s.datid, @@ -1956,7 +1957,7 @@ pg_stat_replication| SELECT s.pid, w.spill_txns, w.spill_count, w.spill_bytes - FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc) + FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid) JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time, spill_txns, spill_count, spill_bytes) ON ((s.pid = w.pid))) LEFT JOIN pg_authid u ON ((s.usesysid = u.oid))); pg_stat_ssl| SELECT s.pid, @@ -1968,7 +1969,7 @@ pg_stat_ssl| SELECT s.pid, s.ssl_client_dn AS client_dn, s.ssl_client_serial AS client_serial, s.ssl_issuer_dn AS issuer_dn - FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc) + FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid) WHERE (s.client_port IS NOT NULL); pg_stat_subscription| SELECT su.oid AS subid, su.subname,