识别Postgres中的连接ID

时间:2011-02-21 20:27:01

标签: delphi postgresql database-connection

我有一个Postgres数据库(9),我正在编写触发器。我希望触发器设置修改时间和记录的用户ID。在Firebird中,您有一个可以在触发器中使用的CONNECTIONID,因此您可以在连接到数据库时向表中添加值(这是一个桌面应用程序,因此连接在应用程序的生命周期内是持久的),类似于这样:

UserId | ConnectionId
---------------------
544    | 3775

然后在触发器中查找connectionid 3775属于userid 544并使用544作为修改记录的用户。

我可以在Postgres中使用类似的东西吗?

4 个答案:

答案 0 :(得分:8)

您可以使用进程ID。它可以通过以下方式检索:

pg_backend_pid()

使用此pid,您还可以使用表pg_stat_activity获取有关当前后端的更多信息,但是您已经应该知道所有内容,因为您正在使用此后端。

或更好。只需创建一个序列,并为每个连接从中检索一个值:

CREATE SEQUENCE 'connectionids';

然后:

SELECT next_val('connectionids');

在每个连接中,检索连接唯一ID。

答案 1 :(得分:5)

一种方法是使用custom_variable_classes配置选项。它似乎旨在允许配置附加模块,但也可用于在当前数据库会话中存储任意值。

需要将以下内容添加到postgresql.conf

custom_variable_classes = 'local'

首次连接数据库时,您可以在自定义类中存储所需的任何信息,如下所示:

SET local.userid = 'foobar';

稍后您可以使用current_setting()函数检索此值:

SELECT current_setting('local.userid');

在日志表中添加条目可能如下所示:

INSERT INTO audit_log VALUES (now(), current_setting('local.userid'), ...)

答案 2 :(得分:1)

虽然它可能适用于您的桌面用例,但请注意进程ID号进行翻转(32768是常见的上限),因此将它们用作识别用户的唯一键可能会遇到问题。如果您最终得到了跟踪用户 - >流程映射的表中先前会话的剩余数据,那么一旦它滚动,就会与分配了相同进程ID的新连接发生冲突。您的应用程序可能只需确保您积极清理旧的映射条目,可能是在启动时根据您描述其操作的方式。

要避免此问题,您需要创建一个包含其他信息的连接密钥,例如会话开始时:

SELECT procpid,backend_start FROM pg_stat_activity WHERE procpid=pg_backend_pid();

必须迭代计算时活动的所有连接,因此它会增加一些开销。从PostgreSQL 8.4开始,可以更有效地执行它:

SELECT procpid,backend_start FROM pg_stat_get_activity(pg_backend_pid());

但是,只有同时激活大量连接才真正重要。

答案 3 :(得分:0)

如果您需要数据库用户,请使用current_user(通过阅读您的问题,我不确定您的需求是什么)。