mirror of
https://github.com/postgres/postgres.git
synced 2025-06-06 00:02:36 -04:00
Add GUC log_lock_waits to log long wait times.
Simon Riggs
This commit is contained in:
parent
f52019cf80
commit
e52c4a6e26
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.113 2007/03/02 23:37:22 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.114 2007/03/03 18:46:40 momjian Exp $ -->
|
||||||
|
|
||||||
<chapter Id="runtime-config">
|
<chapter Id="runtime-config">
|
||||||
<title>Server Configuration</title>
|
<title>Server Configuration</title>
|
||||||
@ -2946,6 +2946,21 @@ SELECT * FROM parent WHERE key = 2400;
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="guc-log-lock-waits" xreflabel="log_lock_waits">
|
||||||
|
<term><varname>log_lock_waits</varname> (<type>boolean</type>)</term>
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>log_lock_waits</> configuration parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Controls whether a log message is produced when a statement waits
|
||||||
|
longer than <xref linkend="guc-deadlock-timeout"> to acquire a
|
||||||
|
lock. This is useful in determining if lock waits are causing
|
||||||
|
poor performance. The default is <literal>off</>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="guc-log-temp-files" xreflabel="log_temp_files">
|
<varlistentry id="guc-log-temp-files" xreflabel="log_temp_files">
|
||||||
<term><varname>log_temp_files</varname> (<type>integer</type>)</term>
|
<term><varname>log_temp_files</varname> (<type>integer</type>)</term>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
@ -3980,17 +3995,18 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
|
|||||||
This is the amount of time, in milliseconds, to wait on a lock
|
This is the amount of time, in milliseconds, to wait on a lock
|
||||||
before checking to see if there is a deadlock condition. The
|
before checking to see if there is a deadlock condition. The
|
||||||
check for deadlock is relatively slow, so the server doesn't run
|
check for deadlock is relatively slow, so the server doesn't run
|
||||||
it every time it waits for a lock. We (optimistically?) assume
|
it every time it waits for a lock. We optimistically assume
|
||||||
that deadlocks are not common in production applications and
|
that deadlocks are not common in production applications and
|
||||||
just wait on the lock for a while before starting the check for a
|
just wait on the lock for a while before starting the check for a
|
||||||
deadlock. Increasing this value reduces the amount of time
|
deadlock. Increasing this value reduces the amount of time
|
||||||
wasted in needless deadlock checks, but slows down reporting of
|
wasted in needless deadlock checks, but slows down reporting of
|
||||||
real deadlock errors. The default is one second (<literal>1s</>),
|
real deadlock errors. The default is one second (<literal>1s</>),
|
||||||
which is probably about the smallest value you would want in
|
which is probably about the smallest value you would want in
|
||||||
practice. On a heavily loaded server you might want to raise it.
|
practice. Set <xref linkend="guc-log-lock-waits"> to log deadlock
|
||||||
|
checks. On a heavily loaded server you might want to raise it.
|
||||||
Ideally the setting should exceed your typical transaction time,
|
Ideally the setting should exceed your typical transaction time,
|
||||||
so as to improve the odds that a lock will be released before
|
so as to improve the odds that a lock will be released before the
|
||||||
the waiter decides to check for deadlock.
|
waiter decides to check for deadlock.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.44 2007/01/05 22:19:38 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.45 2007/03/03 18:46:40 momjian Exp $
|
||||||
*
|
*
|
||||||
* Interface:
|
* Interface:
|
||||||
*
|
*
|
||||||
@ -187,13 +187,14 @@ InitDeadLockChecking(void)
|
|||||||
* deadlock. If resolution is impossible, return TRUE --- the caller
|
* deadlock. If resolution is impossible, return TRUE --- the caller
|
||||||
* is then expected to abort the given proc's transaction.
|
* is then expected to abort the given proc's transaction.
|
||||||
*
|
*
|
||||||
* Caller must already have locked all partitions of the lock tables.
|
* Caller must already have locked all partitions of the lock tables,
|
||||||
|
* so standard error logging/reporting code is handled by caller.
|
||||||
*
|
*
|
||||||
* On failure, deadlock details are recorded in deadlockDetails[] for
|
* On failure, deadlock details are recorded in deadlockDetails[] for
|
||||||
* subsequent printing by DeadLockReport(). That activity is separate
|
* subsequent printing by DeadLockReport(). That activity is separate
|
||||||
* because we don't want to do it while holding all those LWLocks.
|
* because we don't want to do it while holding all those LWLocks.
|
||||||
*/
|
*/
|
||||||
bool
|
DeadlockState
|
||||||
DeadLockCheck(PGPROC *proc)
|
DeadLockCheck(PGPROC *proc)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
@ -204,6 +205,11 @@ DeadLockCheck(PGPROC *proc)
|
|||||||
nPossibleConstraints = 0;
|
nPossibleConstraints = 0;
|
||||||
nWaitOrders = 0;
|
nWaitOrders = 0;
|
||||||
|
|
||||||
|
#ifdef LOCK_DEBUG
|
||||||
|
if (Debug_deadlocks)
|
||||||
|
DumpAllLocks();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Search for deadlocks and possible fixes */
|
/* Search for deadlocks and possible fixes */
|
||||||
if (DeadLockCheckRecurse(proc))
|
if (DeadLockCheckRecurse(proc))
|
||||||
{
|
{
|
||||||
@ -217,7 +223,7 @@ DeadLockCheck(PGPROC *proc)
|
|||||||
if (!FindLockCycle(proc, possibleConstraints, &nSoftEdges))
|
if (!FindLockCycle(proc, possibleConstraints, &nSoftEdges))
|
||||||
elog(FATAL, "deadlock seems to have disappeared");
|
elog(FATAL, "deadlock seems to have disappeared");
|
||||||
|
|
||||||
return true; /* cannot find a non-deadlocked state */
|
return DS_HARD_DEADLOCK; /* cannot find a non-deadlocked state */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply any needed rearrangements of wait queues */
|
/* Apply any needed rearrangements of wait queues */
|
||||||
@ -249,7 +255,11 @@ DeadLockCheck(PGPROC *proc)
|
|||||||
/* See if any waiters for the lock can be woken up now */
|
/* See if any waiters for the lock can be woken up now */
|
||||||
ProcLockWakeup(GetLocksMethodTable(lock), lock);
|
ProcLockWakeup(GetLocksMethodTable(lock), lock);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
if (nWaitOrders > 0)
|
||||||
|
return DS_SOFT_DEADLOCK;
|
||||||
|
else
|
||||||
|
return DS_DEADLOCK_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -896,7 +906,7 @@ DescribeLockTag(StringInfo buf, const LOCKTAG *lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report a detected deadlock, with available details.
|
* Report a detected DS_HARD_DEADLOCK, with available details.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
DeadLockReport(void)
|
DeadLockReport(void)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.184 2007/02/15 23:23:23 alvherre Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.185 2007/03/03 18:46:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -48,6 +48,7 @@
|
|||||||
/* GUC variables */
|
/* GUC variables */
|
||||||
int DeadlockTimeout = 1000;
|
int DeadlockTimeout = 1000;
|
||||||
int StatementTimeout = 0;
|
int StatementTimeout = 0;
|
||||||
|
bool log_lock_waits = false;
|
||||||
|
|
||||||
/* Pointer to this process's PGPROC struct, if any */
|
/* Pointer to this process's PGPROC struct, if any */
|
||||||
PGPROC *MyProc = NULL;
|
PGPROC *MyProc = NULL;
|
||||||
@ -979,6 +980,7 @@ static void
|
|||||||
CheckDeadLock(void)
|
CheckDeadLock(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
DeadlockState deadlock_state = DS_DEADLOCK_NOT_FOUND;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Acquire exclusive lock on the entire shared lock data structures. Must
|
* Acquire exclusive lock on the entire shared lock data structures. Must
|
||||||
@ -1004,21 +1006,12 @@ CheckDeadLock(void)
|
|||||||
* This is quicker than checking our semaphore's state, since no kernel
|
* This is quicker than checking our semaphore's state, since no kernel
|
||||||
* call is needed, and it is safe because we hold the lock partition lock.
|
* call is needed, and it is safe because we hold the lock partition lock.
|
||||||
*/
|
*/
|
||||||
if (MyProc->links.prev == INVALID_OFFSET ||
|
if (MyProc->links.prev != INVALID_OFFSET &&
|
||||||
MyProc->links.next == INVALID_OFFSET)
|
MyProc->links.next != INVALID_OFFSET)
|
||||||
goto check_done;
|
deadlock_state = DeadLockCheck(MyProc);
|
||||||
|
|
||||||
#ifdef LOCK_DEBUG
|
if (deadlock_state == DS_HARD_DEADLOCK)
|
||||||
if (Debug_deadlocks)
|
|
||||||
DumpAllLocks();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!DeadLockCheck(MyProc))
|
|
||||||
{
|
{
|
||||||
/* No deadlock, so keep waiting */
|
|
||||||
goto check_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Oops. We have a deadlock.
|
* Oops. We have a deadlock.
|
||||||
*
|
*
|
||||||
@ -1049,15 +1042,41 @@ CheckDeadLock(void)
|
|||||||
* them anymore. However, RemoveFromWaitQueue took care of waking up any
|
* them anymore. However, RemoveFromWaitQueue took care of waking up any
|
||||||
* such processes.
|
* such processes.
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release locks acquired at head of routine. Order is not critical, so
|
* Release locks acquired at head of routine. Order is not critical, so
|
||||||
* do it back-to-front to avoid waking another CheckDeadLock instance
|
* do it back-to-front to avoid waking another CheckDeadLock instance
|
||||||
* before it can get all the locks.
|
* before it can get all the locks.
|
||||||
*/
|
*/
|
||||||
check_done:
|
|
||||||
for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
|
for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
|
||||||
LWLockRelease(FirstLockMgrLock + i);
|
LWLockRelease(FirstLockMgrLock + i);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Issue any log messages requested.
|
||||||
|
*
|
||||||
|
* Deadlock ERROR messages are issued as part of transaction abort, so
|
||||||
|
* these messages should not raise error states intentionally.
|
||||||
|
*/
|
||||||
|
if (log_lock_waits)
|
||||||
|
{
|
||||||
|
switch (deadlock_state)
|
||||||
|
{
|
||||||
|
case DS_SOFT_DEADLOCK:
|
||||||
|
ereport(LOG,
|
||||||
|
(errmsg("deadlock avoided by rearranging lock order")));
|
||||||
|
break;
|
||||||
|
case DS_DEADLOCK_NOT_FOUND:
|
||||||
|
ereport(LOG,
|
||||||
|
(errmsg("statement waiting for lock for at least %d ms",
|
||||||
|
DeadlockTimeout)));
|
||||||
|
break;
|
||||||
|
case DS_HARD_DEADLOCK:
|
||||||
|
break; /* ERROR message handled during abort */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.377 2007/02/23 21:36:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.378 2007/03/03 18:46:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------
|
*--------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -811,6 +811,14 @@ static struct config_bool ConfigureNamesBool[] =
|
|||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
{"log_lock_waits", PGC_SIGHUP, LOGGING_WHAT,
|
||||||
|
gettext_noop("Logs long lock wait events."),
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
&log_lock_waits,
|
||||||
|
false, NULL, NULL
|
||||||
|
},
|
||||||
{
|
{
|
||||||
{"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
|
{"log_hostname", PGC_SIGHUP, LOGGING_WHAT,
|
||||||
gettext_noop("Logs the host name in the connection logs."),
|
gettext_noop("Logs the host name in the connection logs."),
|
||||||
|
@ -340,7 +340,7 @@
|
|||||||
# e.g. '<%u%%%d> '
|
# e.g. '<%u%%%d> '
|
||||||
#log_statement = 'none' # none, ddl, mod, all
|
#log_statement = 'none' # none, ddl, mod, all
|
||||||
#log_hostname = off
|
#log_hostname = off
|
||||||
|
#log_lock_waits = off # Log lock waits longer than deadlock_timeout
|
||||||
#log_temp_files = -1 # Log temporary files equal or larger
|
#log_temp_files = -1 # Log temporary files equal or larger
|
||||||
# than the specified number of kilobytes.
|
# than the specified number of kilobytes.
|
||||||
# -1 disables; 0 logs all temp files
|
# -1 disables; 0 logs all temp files
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.103 2007/01/05 22:19:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.104 2007/03/03 18:46:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -394,6 +394,13 @@ typedef enum
|
|||||||
LOCKACQUIRE_ALREADY_HELD /* incremented count for lock already held */
|
LOCKACQUIRE_ALREADY_HELD /* incremented count for lock already held */
|
||||||
} LockAcquireResult;
|
} LockAcquireResult;
|
||||||
|
|
||||||
|
/* Deadlock states identified by DeadlockCheck() */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DS_DEADLOCK_NOT_FOUND, /* no deadlock found within database server */
|
||||||
|
DS_SOFT_DEADLOCK, /* deadlock, but lock queues rearrangeable */
|
||||||
|
DS_HARD_DEADLOCK /* deadlock, no way out but ERROR */
|
||||||
|
} DeadlockState;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The lockmgr's shared hash tables are partitioned to reduce contention.
|
* The lockmgr's shared hash tables are partitioned to reduce contention.
|
||||||
@ -442,7 +449,7 @@ extern void lock_twophase_postcommit(TransactionId xid, uint16 info,
|
|||||||
extern void lock_twophase_postabort(TransactionId xid, uint16 info,
|
extern void lock_twophase_postabort(TransactionId xid, uint16 info,
|
||||||
void *recdata, uint32 len);
|
void *recdata, uint32 len);
|
||||||
|
|
||||||
extern bool DeadLockCheck(PGPROC *proc);
|
extern DeadlockState DeadLockCheck(PGPROC *proc);
|
||||||
extern void DeadLockReport(void);
|
extern void DeadLockReport(void);
|
||||||
extern void RememberSimpleDeadLock(PGPROC *proc1,
|
extern void RememberSimpleDeadLock(PGPROC *proc1,
|
||||||
LOCKMODE lockmode,
|
LOCKMODE lockmode,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.94 2007/02/15 23:23:23 alvherre Exp $
|
* $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.95 2007/03/03 18:46:40 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -127,6 +127,7 @@ typedef struct PROC_HDR
|
|||||||
/* configurable options */
|
/* configurable options */
|
||||||
extern int DeadlockTimeout;
|
extern int DeadlockTimeout;
|
||||||
extern int StatementTimeout;
|
extern int StatementTimeout;
|
||||||
|
extern bool log_lock_waits;
|
||||||
|
|
||||||
extern volatile bool cancel_from_timeout;
|
extern volatile bool cancel_from_timeout;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user