↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2
历史版本PostgreSQL 8.3 已于 2013 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

26.4. 动态追踪 #

PostgreSQL提供了功能来支持数据库服务器的动态追踪。这样就允许在代码中的特定点上调用外部工具来追踪执行过程。目前,这一设施主要供数据库开发人员使用,因为它需要对代码相当熟悉。

源码中已经插入了若干跟踪点(通常称为探针)。默认情况下这些探针是禁用的,用户需要显式地告诉配置脚本使这些探针在PostgreSQL中可用。

目前只支持 DTrace 工具,它只在 Solaris Express 和 Solaris 10+ 上可用。预计 DTrace 将来也会在 FreeBSD 和 Mac OS X 上可用。通过修改src/include/pg_trace.h中PG_TRACE宏的定义,理论上也可以支持其他动态追踪工具。

26.4.1. 为动态追踪编译 #

默认情况下,跟踪点是禁用的,因此你将需要显式地告诉配置脚本让探针在PostgreSQL中可用。要包括 DTrace 支持,在配置时指定--enable-dtrace。更多信息请见第 15.5 节。

26.4.2. 内建的跟踪点 #

源码中提供了一些标准跟踪点(当然,还可以根据具体问题的需要添加更多)。它们如表 26.3所示。

表 26.3. 内建的跟踪点

名称 参数 概述
transaction__start (int transactionId) 一个新事务的开始。
transaction__commit (int transactionId) 一个事务成功完成。
transaction__abort (int transactionId) 一个事务未成功完成。
lwlock__acquire (int lockid, int mode) 已获取一个 LWLock。
lwlock__release (int lockid, int mode) 已释放一个 LWLock。
lwlock__startwait (int lockid, int mode) 一个 LWLock 不能立即获取,某个后端已开始等待该锁变为可用。
lwlock__endwait (int lockid, int mode) 某个后端结束了对一个 LWLock 的等待。
lwlock__condacquire (int lockid, int mode) 调用者指定不等待时成功获取了一个 LWLock。
lwlock__condacquire__fail (int lockid, int mode) 调用者指定不等待时未能获取一个 LWLock。
lock__startwait (int locktag_field2, int lockmode) 对一个重量级锁(lmgr 锁)的请求因锁不可用已开始等待。
lock__endwait (int locktag_field2, int lockmode) 对一个重量级锁(lmgr 锁)的请求结束等待(即已获取该锁)。

26.4.3. 使用跟踪点 #

下面的示例展示了一个分析系统中事务计数的 DTrace 脚本,可以用来代替一次性能测试之前和之后的pg_stat_database快照:

#!/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;
}

注意,在使用 D 脚本时,跟踪点名称中的双下划线需要替换为连字符。执行时,该示例 D 脚本的输出如下:

# ./txn_count.d `pgrep -n postgres`
^C

Start                                          71
Commit                                         70
Total time (ns)                        2312105013

你应当记住,跟踪程序需要在使用前仔细编写和调试,否则收集到的跟踪信息可能毫无意义。在发现问题时,大多数情况是测量手段本身有错,而不是底层系统的问题。在讨论通过动态追踪发现的信息时,务必附上所使用的脚本,以便它也能被检查和讨论。

26.4.4. 定义跟踪点 #

开发者可以在代码中任何想要的地方定义新的跟踪点,不过这需要重新编译。

可以使用某一个跟踪宏插入一个跟踪点。根据在该跟踪点上可供检查的变量数量的不同,应选用不同的宏。只使用跟踪点名称,用一行就可以跟踪一个事件的发生,例如:

PG_TRACE (my__new__trace__point);

更复杂的跟踪点可以使用与跟踪点名称后面参数数量相对应的PG_TRACEn宏,为动态追踪工具提供一个或多个可供检查的变量:

PG_TRACE3 (my__complex__event, varX, varY, varZ);

transaction__start 跟踪点的定义如下所示:

static void
StartTransaction(void)
{
    ...

    /*
     * generate a new transaction id
     */
    s->transactionId = GetNewTransactionId(false);

    XactLockTableInsert(s->transactionId);

    PG_TRACE1(transaction__start, s->transactionId);

    ...
}    

注意事务 ID 是如何被提供给动态追踪工具的。

动态追踪工具可能要求你进一步定义这些跟踪点。例如,DTrace 要求你把新的探针添加到文件src/backend/utils/probes.d中,如下所示:

provider postgresql {
      ...
      probe transaction__start(int);
      ...
 };

你应当注意,为探针参数指定的数据类型要与PG_TRACE宏中使用的变量的数据类型匹配。这在编译时不做检查。你可以通过重新编译、运行新的二进制文件并以 root 身份执行如下 DTrace 命令来检查新添加的跟踪点是否可用:

dtrace -l -n transaction-start

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。