Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4b7ae4a

Browse files
committed
Report the current queries of all backends involved in a deadlock
(if they'd be visible to the current user in pg_stat_activity).This might look like it's subject to race conditions, but it's actuallypretty safe because at the time DeadLockReport() is constructing thereport, we haven't yet aborted our transaction and so we can expect thateveryone else involved in the deadlock is still blocked on some lock.(There are corner cases where that might not be true, such as a statementtimeout triggering in another backend before we finish reporting; but atworst we'd report a misleading activity string, so it seems acceptableconsidering the usefulness of reporting the queries.)Original patch by Itagaki Takahiro, heavily modified by me.
1 parentdf812e9 commit4b7ae4a

File tree

3 files changed

+103
-15
lines changed

3 files changed

+103
-15
lines changed

‎src/backend/postmaster/pgstat.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*Copyright (c) 2001-2008, PostgreSQL Global Development Group
1515
*
16-
*$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.169 2008/01/01 19:45:51 momjian Exp $
16+
*$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.170 2008/03/21 21:08:31 tgl Exp $
1717
* ----------
1818
*/
1919
#include"postgres.h"
@@ -2036,6 +2036,80 @@ pgstat_read_current_status(void)
20362036
}
20372037

20382038

2039+
/* ----------
2040+
* pgstat_get_backend_current_activity() -
2041+
*
2042+
*Return a string representing the current activity of the backend with
2043+
*the specified PID. This looks directly at the BackendStatusArray,
2044+
*and so will provide current information regardless of the age of our
2045+
*transaction's snapshot of the status array.
2046+
*
2047+
*It is the caller's responsibility to invoke this only for backends whose
2048+
*state is expected to remain stable while the result is in use. The
2049+
*only current use is in deadlock reporting, where we can expect that
2050+
*the target backend is blocked on a lock. (There are corner cases
2051+
*where the target's wait could get aborted while we are looking at it,
2052+
*but the very worst consequence is to return a pointer to a string
2053+
*that's been changed, so we won't worry too much.)
2054+
*
2055+
*Note: return strings for special cases match pg_stat_get_backend_activity.
2056+
* ----------
2057+
*/
2058+
constchar*
2059+
pgstat_get_backend_current_activity(intpid)
2060+
{
2061+
PgBackendStatus*beentry;
2062+
inti;
2063+
2064+
beentry=BackendStatusArray;
2065+
for (i=1;i <=MaxBackends;i++)
2066+
{
2067+
/*
2068+
* Although we expect the target backend's entry to be stable, that
2069+
* doesn't imply that anyone else's is. To avoid identifying the
2070+
* wrong backend, while we check for a match to the desired PID we
2071+
* must follow the protocol of retrying if st_changecount changes
2072+
* while we examine the entry, or if it's odd. (This might be
2073+
* unnecessary, since fetching or storing an int is almost certainly
2074+
* atomic, but let's play it safe.) We use a volatile pointer here
2075+
* to ensure the compiler doesn't try to get cute.
2076+
*/
2077+
volatilePgBackendStatus*vbeentry=beentry;
2078+
boolfound;
2079+
2080+
for (;;)
2081+
{
2082+
intsave_changecount=vbeentry->st_changecount;
2083+
2084+
found= (vbeentry->st_procpid==pid);
2085+
2086+
if (save_changecount==vbeentry->st_changecount&&
2087+
(save_changecount&1)==0)
2088+
break;
2089+
2090+
/* Make sure we can break out of loop if stuck... */
2091+
CHECK_FOR_INTERRUPTS();
2092+
}
2093+
2094+
if (found)
2095+
{
2096+
/* Now it is safe to use the non-volatile pointer */
2097+
if (!superuser()&&beentry->st_userid!=GetUserId())
2098+
return"<insufficient privilege>";
2099+
elseif (*(beentry->st_activity)=='\0')
2100+
return"<command string not enabled>";
2101+
else
2102+
returnbeentry->st_activity;
2103+
}
2104+
2105+
beentry++;
2106+
}
2107+
2108+
/* If we get here, caller is in error ... */
2109+
return"<backend information not available>";
2110+
}
2111+
2112+
20392113
/* ------------------------------------------------------------
20402114
* Local support functions follow
20412115
* ------------------------------------------------------------

‎src/backend/storage/lmgr/deadlock.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.51 2008/01/01 19:45:52 momjian Exp $
15+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.52 2008/03/21 21:08:31 tgl Exp $
1616
*
1717
*Interface:
1818
*
@@ -26,6 +26,7 @@
2626
#include"postgres.h"
2727

2828
#include"miscadmin.h"
29+
#include"pgstat.h"
2930
#include"storage/lmgr.h"
3031
#include"storage/proc.h"
3132
#include"utils/memutils.h"
@@ -878,12 +879,14 @@ PrintLockQueue(LOCK *lock, const char *info)
878879
void
879880
DeadLockReport(void)
880881
{
881-
StringInfoDatabuf;
882-
StringInfoDatabuf2;
882+
StringInfoDatadetailbuf;
883+
StringInfoDatacontextbuf;
884+
StringInfoDatalocktagbuf;
883885
inti;
884886

885-
initStringInfo(&buf);
886-
initStringInfo(&buf2);
887+
initStringInfo(&detailbuf);
888+
initStringInfo(&contextbuf);
889+
initStringInfo(&locktagbuf);
887890

888891
for (i=0;i<nDeadlockDetails;i++)
889892
{
@@ -896,26 +899,36 @@ DeadLockReport(void)
896899
else
897900
nextpid=deadlockDetails[0].pid;
898901

899-
if (i>0)
900-
appendStringInfoChar(&buf,'\n');
902+
/* reset locktagbuf to hold next object description */
903+
resetStringInfo(&locktagbuf);
901904

902-
/* reset buf2 to hold next object description */
903-
resetStringInfo(&buf2);
905+
DescribeLockTag(&locktagbuf,&info->locktag);
904906

905-
DescribeLockTag(&buf2,&info->locktag);
907+
if (i>0)
908+
appendStringInfoChar(&detailbuf,'\n');
906909

907-
appendStringInfo(&buf,
910+
appendStringInfo(&detailbuf,
908911
_("Process %d waits for %s on %s; blocked by process %d."),
909912
info->pid,
910913
GetLockmodeName(info->locktag.locktag_lockmethodid,
911914
info->lockmode),
912-
buf2.data,
915+
locktagbuf.data,
913916
nextpid);
917+
918+
if (i>0)
919+
appendStringInfoChar(&contextbuf,'\n');
920+
921+
appendStringInfo(&contextbuf,
922+
_("Process %d: %s"),
923+
info->pid,
924+
pgstat_get_backend_current_activity(info->pid));
914925
}
926+
915927
ereport(ERROR,
916928
(errcode(ERRCODE_T_R_DEADLOCK_DETECTED),
917929
errmsg("deadlock detected"),
918-
errdetail("%s",buf.data)));
930+
errdetail("%s",detailbuf.data),
931+
errcontext("%s",contextbuf.data)));
919932
}
920933

921934
/*

‎src/include/pgstat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
*Copyright (c) 2001-2008, PostgreSQL Global Development Group
77
*
8-
*$PostgreSQL: pgsql/src/include/pgstat.h,v 1.71 2008/01/01 19:45:56 momjian Exp $
8+
*$PostgreSQL: pgsql/src/include/pgstat.h,v 1.72 2008/03/21 21:08:31 tgl Exp $
99
* ----------
1010
*/
1111
#ifndefPGSTAT_H
@@ -507,6 +507,7 @@ extern void pgstat_bestart(void);
507507
externvoidpgstat_report_activity(constchar*what);
508508
externvoidpgstat_report_xact_timestamp(TimestampTztstamp);
509509
externvoidpgstat_report_waiting(boolwaiting);
510+
externconstchar*pgstat_get_backend_current_activity(intpid);
510511

511512
externvoidpgstat_initstats(Relationrel);
512513

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp