-
+
Monitoring Database Activity
+
+
+
Dynamic Tracing
+
+
+
+
+
PostgreSQL provides facilities to support
+ dynamic tracing of the database server. This allows an external
+ utility to be called at specific points in the code and thereby trace
+ execution. Currently, this facility is primarily intended for use by
+ database developers, as it requires substantial familiarity with the code.
+
+
+ A number of trace points, often called probes, are already inserted
+ into the source code. By default these probes are disabled, and
+ the user needs to explicitly tell the configure script to make the
+ probes available in
PostgreSQL.
+
+
+ Currently, only the DTrace utility is supported, which is only available
+ on Solaris Express and Solaris 10+. It is expected that DTrace will
+ be available in the future on FreeBSD and Mac OS X.
+ Supporting other dynamic tracing utilities is theoretically possible by
+ changing the definitions for the PG_TRACE> macros in
+ src/include/pg_trace.h>.
+
+
+
+
Compiling for Dynamic Trace
+
+ By default, trace points are disabled, so you will need to
+ explicitly tell the configure script to make the probes available
+ in
PostgreSQL. To include DTrace support
+ in a 32-bit binary, specify
+ For example:
+ $ ./configure --enable-dtrace ...
+
+ To include DTrace support in a 64-bit binary, specify
+
+ and DTRACEFLAGS="-64"> to configure. For example,
+ using the gcc compiler:
+ $ ./configure CC='gcc -m64' --enable-dtrace DTRACEFLAGS='-64' ...
+
+ Using Sun's compiler:
+ $ ./configure CC='/path_to_sun_compiler/cc -xtarget=native64' --enable-dtrace DTRACEFLAGS='-64' ...
+
+
+
+
+
+
Built-in Trace Points
+
+ A few standard trace points are provided in the source code
+ (of course, more can be added as needed for a particular problem).
+ These are:
+
+
+
+
Built-in Trace Points
+
+
+ |
+ Name
+ Parameters
+ Overview
+
+
+
+
+ |
+ transaction__start
+ (int transactionId)
+ The start of a new transaction.
+
+ |
+ transaction__commit
+ (int transactionId)
+ The successful completion of a transaction.
+
+ |
+ transaction__abort
+ (int transactionId)
+ The unsuccessful completion of a transaction.
+
+
+ |
+ lwlock__acquire
+ (int lockid, int mode)
+ An LWLock has been acquired.
+
+ |
+ lwlock__release
+ (int lockid, int mode)
+ An LWLock has been released.
+
+ |
+ lwlock__startwait
+ (int lockid, int mode)
+ An LWLock was not immediately available and a backend
+ has begun to wait for the lock to become available.
+
+
+ |
+ lwlock__endwait
+ (int lockid, int mode)
+ A backend has been released from its wait for an LWLock.
+
+
+ |
+ lwlock__condacquire
+ (int lockid, int mode)
+ An LWLock was successfully acquired when the caller specified no
+ waiting.
+
+
+ |
+ lwlock__condacquire__fail
+ (int lockid, int mode)
+ An LWLock was not successfully acquired when the caller specified
+ no waiting.
+
+
+ |
+ lock__startwait
+ (int locktag_field2, int lockmode)
+ A request for a heavyweight lock (lmgr lock) has begun to wait
+ because the lock is not available.
+
+
+ |
+ lock__endwait
+ (int locktag_field2, int lockmode)
+ A request for a heavyweight lock (lmgr lock) has finished waiting
+ (i.e., has acquired the lock).
+
+
+
+
+
+
+
+
+
Using Trace Points
+
+ The example below shows a DTrace script for analyzing transaction
+ counts on the system, as an alternative to snapshotting
+ pg_stat_database> before and after a performance test.
+#!/usr/sbin/dtrace -qs
+
+postgresql$1:::transaction-start
+{
+ @start["Start"] = count();
+ self->ts = timestamp;
+}
+
+postgresql$1:::transaction-abort
+{
+ @abort["Abort"] = count();
+}
+
+postgresql$1:::transaction-commit
+/self->ts/
+{
+ @commit["Commit"] = count();
+ @time["Total time (ns)"] = sum(timestamp - self->ts);
+ self->ts=0;
+}
+
+ Note how the double underline in trace point names needs to
+ be replaced by a hyphen when using D script.
+ When executed, the example D script gives output such as:
+# ./txn_count.d `pgrep -n postgres`
+^C
+
+Start 71
+Commit 70
+Abort 1
+Total time (ns) 2312105013
+
+
+ You should remember that trace programs need to be carefully written and
+ debugged prior to their use, otherwise the trace information collected may
+ be meaningless. In most cases where problems are found it is the
+ instrumentation that is at fault, not the underlying system. When
+ discussing information found using dynamic tracing, be sure to enclose
+ the script used to allow that too to be checked and discussed.
+
+
+
+
+
Defining Trace Points
+
+ New trace points can be defined within the code wherever the developer
+ desires, though this will require a re-compile.
+
+
+ A trace point can be inserted by using one of the
+ trace macros. These are chosen according to how many variables will
+ be made available for inspection at that trace point. Tracing the
+ occurrence of an event can be achieved with a single line, using
+ just the trace point name, e.g.
+ PG_TRACE (my__new__trace__point);
+
+ More complex trace points can be provided with one or more variables
+ for inspection by the dynamic tracing utility by using the
+ PG_TRACE>n> macro that corresponds to the number
+ of parameters after the trace point name:
+ PG_TRACE3 (my__complex__event, varX, varY, varZ);
+
+ The definition of the transaction__start trace point is shown below:
+static void
+StartTransaction(void)
+{
+ ...
+
+ /*
+ * generate a new transaction id
+ */
+ s->transactionId = GetNewTransactionId(false);
+
+ XactLockTableInsert(s->transactionId);
+
+ PG_TRACE1(transaction__start, s->transactionId);
+
+ ...
+}
+
+ Note how the transaction ID is made available to the dynamic tracing
+ utility.
+
+
+ The dynamic tracing utility may require you to further define these trace
+ points. For example, DTrace requires you to add new probes to the file
+ src/backend/utils/probes.d> as shown here:
+provider postgresql {
+ ...
+ probe transaction__start(int);
+ ...
+ };
+
+
+
+ You should take care that the datatypes specified for the probe arguments
+ match the datatypes of the variables used in the PG_TRACE>
+ macro. This is not checked at compile time. You can check that your newly
+ added trace point is available by recompiling, then running the new binary,
+ and as root, executing a DTrace command such as:
+dtrace -l -n transaction-start
+
+
+
+
+
+