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

Commit 53be0b1

Browse files
committed
Provide much better wait information in pg_stat_activity.
When a process is waiting for a heavyweight lock, we will now indicate the type of heavyweight lock for which it is waiting. Also, you can now see when a process is waiting for a lightweight lock - in which case we will indicate the individual lock name or the tranche, as appropriate - or for a buffer pin. Amit Kapila, Ildus Kurbangaliev, reviewed by me. Lots of helpful discussion and suggestions by many others, including Alexander Korotkov, Vladimir Borodin, and many others.
1 parent a3a8309 commit 53be0b1

File tree

24 files changed

+794
-102
lines changed

24 files changed

+794
-102
lines changed

doc/src/sgml/monitoring.sgml

+403-11
Large diffs are not rendered by default.

src/backend/access/transam/xact.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -2447,13 +2447,14 @@ AbortTransaction(void)
24472447
*/
24482448
LWLockReleaseAll();
24492449

2450+
/* Clear wait information and command progress indicator */
2451+
pgstat_report_wait_end();
2452+
pgstat_progress_end_command();
2453+
24502454
/* Clean up buffer I/O and buffer context locks, too */
24512455
AbortBufferIO();
24522456
UnlockBuffers();
24532457

2454-
/* Clear command progress indicator */
2455-
pgstat_progress_end_command();
2456-
24572458
/* Reset WAL record construction state */
24582459
XLogResetInsertion();
24592460

@@ -4541,9 +4542,10 @@ AbortSubTransaction(void)
45414542
*/
45424543
LWLockReleaseAll();
45434544

4545+
pgstat_report_wait_end();
4546+
pgstat_progress_end_command();
45444547
AbortBufferIO();
45454548
UnlockBuffers();
4546-
pgstat_progress_end_command();
45474549

45484550
/* Reset WAL record construction state */
45494551
XLogResetInsertion();
@@ -4653,6 +4655,9 @@ AbortSubTransaction(void)
46534655
*/
46544656
XactReadOnly = s->prevXactReadOnly;
46554657

4658+
/* Report wait end here, when there is no further possibility of wait */
4659+
pgstat_report_wait_end();
4660+
46564661
RESUME_INTERRUPTS();
46574662
}
46584663

src/backend/bootstrap/bootstrap.c

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "miscadmin.h"
2727
#include "nodes/makefuncs.h"
2828
#include "pg_getopt.h"
29+
#include "pgstat.h"
2930
#include "postmaster/bgwriter.h"
3031
#include "postmaster/startup.h"
3132
#include "postmaster/walwriter.h"
@@ -534,6 +535,7 @@ static void
534535
ShutdownAuxiliaryProcess(int code, Datum arg)
535536
{
536537
LWLockReleaseAll();
538+
pgstat_report_wait_end();
537539
}
538540

539541
/* ----------------------------------------------------------------

src/backend/catalog/system_views.sql

+2-1
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ CREATE VIEW pg_stat_activity AS
636636
S.xact_start,
637637
S.query_start,
638638
S.state_change,
639-
S.waiting,
639+
S.wait_event_type,
640+
S.wait_event,
640641
S.state,
641642
S.backend_xid,
642643
s.backend_xmin,

src/backend/postmaster/bgwriter.c

+3
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ BackgroundWriterMain(void)
224224
* It's not clear we need it elsewhere, but shouldn't hurt.
225225
*/
226226
smgrcloseall();
227+
228+
/* Report wait end here, when there is no further possibility of wait */
229+
pgstat_report_wait_end();
227230
}
228231

229232
/* We can now handle ereport(ERROR) */

src/backend/postmaster/checkpointer.c

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ CheckpointerMain(void)
273273
* files.
274274
*/
275275
LWLockReleaseAll();
276+
pgstat_report_wait_end();
276277
AbortBufferIO();
277278
UnlockBuffers();
278279
/* buffer pins are released here: */

src/backend/postmaster/pgstat.c

+86-30
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@
4848
#include "postmaster/autovacuum.h"
4949
#include "postmaster/fork_process.h"
5050
#include "postmaster/postmaster.h"
51-
#include "storage/proc.h"
5251
#include "storage/backendid.h"
5352
#include "storage/dsm.h"
5453
#include "storage/fd.h"
5554
#include "storage/ipc.h"
5655
#include "storage/latch.h"
56+
#include "storage/lmgr.h"
5757
#include "storage/pg_shmem.h"
5858
#include "storage/procsignal.h"
5959
#include "storage/sinvaladt.h"
@@ -2723,7 +2723,6 @@ pgstat_bestart(void)
27232723
#else
27242724
beentry->st_ssl = false;
27252725
#endif
2726-
beentry->st_waiting = false;
27272726
beentry->st_state = STATE_UNDEFINED;
27282727
beentry->st_appname[0] = '\0';
27292728
beentry->st_activity[0] = '\0';
@@ -2810,6 +2809,8 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
28102809
{
28112810
if (beentry->st_state != STATE_DISABLED)
28122811
{
2812+
volatile PGPROC *proc = MyProc;
2813+
28132814
/*
28142815
* track_activities is disabled, but we last reported a
28152816
* non-disabled state. As our final update, change the state and
@@ -2820,9 +2821,9 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
28202821
beentry->st_state_start_timestamp = 0;
28212822
beentry->st_activity[0] = '\0';
28222823
beentry->st_activity_start_timestamp = 0;
2823-
/* st_xact_start_timestamp and st_waiting are also disabled */
2824+
/* st_xact_start_timestamp and wait_event_info are also disabled */
28242825
beentry->st_xact_start_timestamp = 0;
2825-
beentry->st_waiting = false;
2826+
proc->wait_event_info = 0;
28262827
pgstat_increment_changecount_after(beentry);
28272828
}
28282829
return;
@@ -2978,32 +2979,6 @@ pgstat_report_xact_timestamp(TimestampTz tstamp)
29782979
pgstat_increment_changecount_after(beentry);
29792980
}
29802981

2981-
/* ----------
2982-
* pgstat_report_waiting() -
2983-
*
2984-
* Called from lock manager to report beginning or end of a lock wait.
2985-
*
2986-
* NB: this *must* be able to survive being called before MyBEEntry has been
2987-
* initialized.
2988-
* ----------
2989-
*/
2990-
void
2991-
pgstat_report_waiting(bool waiting)
2992-
{
2993-
volatile PgBackendStatus *beentry = MyBEEntry;
2994-
2995-
if (!pgstat_track_activities || !beentry)
2996-
return;
2997-
2998-
/*
2999-
* Since this is a single-byte field in a struct that only this process
3000-
* may modify, there seems no need to bother with the st_changecount
3001-
* protocol. The update must appear atomic in any case.
3002-
*/
3003-
beentry->st_waiting = waiting;
3004-
}
3005-
3006-
30072982
/* ----------
30082983
* pgstat_read_current_status() -
30092984
*
@@ -3119,6 +3094,87 @@ pgstat_read_current_status(void)
31193094
localBackendStatusTable = localtable;
31203095
}
31213096

3097+
/* ----------
3098+
* pgstat_get_wait_event_type() -
3099+
*
3100+
* Return a string representing the current wait event type, backend is
3101+
* waiting on.
3102+
*/
3103+
const char *
3104+
pgstat_get_wait_event_type(uint32 wait_event_info)
3105+
{
3106+
uint8 classId;
3107+
const char *event_type;
3108+
3109+
/* report process as not waiting. */
3110+
if (wait_event_info == 0)
3111+
return NULL;
3112+
3113+
wait_event_info = wait_event_info >> 24;
3114+
classId = wait_event_info & 0XFF;
3115+
3116+
switch (classId)
3117+
{
3118+
case WAIT_LWLOCK_NAMED:
3119+
event_type = "LWLockNamed";
3120+
break;
3121+
case WAIT_LWLOCK_TRANCHE:
3122+
event_type = "LWLockTranche";
3123+
break;
3124+
case WAIT_LOCK:
3125+
event_type = "Lock";
3126+
break;
3127+
case WAIT_BUFFER_PIN:
3128+
event_type = "BufferPin";
3129+
break;
3130+
default:
3131+
event_type = "???";
3132+
break;
3133+
}
3134+
3135+
return event_type;
3136+
}
3137+
3138+
/* ----------
3139+
* pgstat_get_wait_event() -
3140+
*
3141+
* Return a string representing the current wait event, backend is
3142+
* waiting on.
3143+
*/
3144+
const char *
3145+
pgstat_get_wait_event(uint32 wait_event_info)
3146+
{
3147+
uint8 classId;
3148+
uint16 eventId;
3149+
const char *event_name;
3150+
3151+
/* report process as not waiting. */
3152+
if (wait_event_info == 0)
3153+
return NULL;
3154+
3155+
eventId = wait_event_info & ((1 << 24) - 1);
3156+
wait_event_info = wait_event_info >> 24;
3157+
classId = wait_event_info & 0XFF;
3158+
3159+
switch (classId)
3160+
{
3161+
case WAIT_LWLOCK_NAMED:
3162+
case WAIT_LWLOCK_TRANCHE:
3163+
event_name = GetLWLockIdentifier(classId, eventId);
3164+
break;
3165+
case WAIT_LOCK:
3166+
event_name = GetLockNameFromTagType(eventId);
3167+
break;
3168+
case WAIT_BUFFER_PIN:
3169+
event_name = "BufferPin";
3170+
break;
3171+
default:
3172+
event_name = "unknown wait event";
3173+
break;
3174+
}
3175+
3176+
return event_name;
3177+
}
31223178

31233179
/* ----------
31243180
* pgstat_get_backend_current_activity() -

src/backend/postmaster/walwriter.c

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "access/xlog.h"
4848
#include "libpq/pqsignal.h"
4949
#include "miscadmin.h"
50+
#include "pgstat.h"
5051
#include "postmaster/walwriter.h"
5152
#include "storage/bufmgr.h"
5253
#include "storage/fd.h"
@@ -168,6 +169,7 @@ WalWriterMain(void)
168169
* about in walwriter, but we do have LWLocks, and perhaps buffers?
169170
*/
170171
LWLockReleaseAll();
172+
pgstat_report_wait_end();
171173
AbortBufferIO();
172174
UnlockBuffers();
173175
/* buffer pins are released here: */

src/backend/replication/walsender.c

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "libpq/pqformat.h"
5656
#include "miscadmin.h"
5757
#include "nodes/replnodes.h"
58+
#include "pgstat.h"
5859
#include "replication/basebackup.h"
5960
#include "replication/decode.h"
6061
#include "replication/logical.h"
@@ -252,6 +253,7 @@ void
252253
WalSndErrorCleanup(void)
253254
{
254255
LWLockReleaseAll();
256+
pgstat_report_wait_end();
255257

256258
if (sendFile >= 0)
257259
{

src/backend/storage/buffer/bufmgr.c

+5
Original file line numberDiff line numberDiff line change
@@ -3351,6 +3351,9 @@ LockBufferForCleanup(Buffer buffer)
33513351
UnlockBufHdr(bufHdr);
33523352
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
33533353

3354+
/* Report the wait */
3355+
pgstat_report_wait_start(WAIT_BUFFER_PIN, 0);
3356+
33543357
/* Wait to be signaled by UnpinBuffer() */
33553358
if (InHotStandby)
33563359
{
@@ -3364,6 +3367,8 @@ LockBufferForCleanup(Buffer buffer)
33643367
else
33653368
ProcWaitForSignal();
33663369

3370+
pgstat_report_wait_end();
3371+
33673372
/*
33683373
* Remove flag marking us as waiter. Normally this will not be set
33693374
* anymore, but ProcWaitForSignal() can return for other signals as

src/backend/storage/lmgr/lmgr.c

+23
Original file line numberDiff line numberDiff line change
@@ -994,3 +994,26 @@ DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
994994
break;
995995
}
996996
}
997+
998+
/*
999+
* GetLockNameFromTagType
1000+
*
1001+
* Given locktag type, return the corresponding lock name.
1002+
*/
1003+
const char *
1004+
GetLockNameFromTagType(uint16 locktag_type)
1005+
{
1006+
const char *locktypename;
1007+
char tnbuf[32];
1008+
1009+
if (locktag_type <= LOCKTAG_LAST_TYPE)
1010+
locktypename = LockTagTypeNames[locktag_type];
1011+
else
1012+
{
1013+
snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
1014+
(int) locktag_type);
1015+
locktypename = tnbuf;
1016+
}
1017+
1018+
return locktypename;
1019+
}

src/backend/storage/lmgr/lock.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1676,7 +1676,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
16761676
set_ps_display(new_status, false);
16771677
new_status[len] = '\0'; /* truncate off " waiting" */
16781678
}
1679-
pgstat_report_waiting(true);
1679+
pgstat_report_wait_start(WAIT_LOCK, locallock->tag.lock.locktag_type);
16801680

16811681
awaitedLock = locallock;
16821682
awaitedOwner = owner;
@@ -1724,7 +1724,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
17241724
/* In this path, awaitedLock remains set until LockErrorCleanup */
17251725

17261726
/* Report change to non-waiting status */
1727-
pgstat_report_waiting(false);
1727+
pgstat_report_wait_end();
17281728
if (update_process_title)
17291729
{
17301730
set_ps_display(new_status, false);
@@ -1739,7 +1739,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
17391739
awaitedLock = NULL;
17401740

17411741
/* Report change to non-waiting status */
1742-
pgstat_report_waiting(false);
1742+
pgstat_report_wait_end();
17431743
if (update_process_title)
17441744
{
17451745
set_ps_display(new_status, false);

0 commit comments

Comments
 (0)