有没有办法将应用程序上下文传递给非Sybase数据库服务器中的数据库连接(类似于Sybase中的set_appcontext)?

时间:2011-01-24 18:03:41

标签: mysql sql oracle sybase

Sybase有一种方法可以让应用程序将"context" data - 例如应用程序的最终用户名等 - 与数据库连接会话进行通信。上下文数据基本上只是一组键值对,它们通过set_appcontext / get_appcontext存储过程存储/检索。

问题

其他主要数据库服务器(MSSQL / Oracle / MySQL)是否具有将应用程序上下文传递给会话的工具,类似于Sybase的set_appcontext

详情

应用程序上下文的一个特定实际用途是当您将具有中间层的应用程序作为非常特定的通用数据库用户连接到数据库时(示例包括用于在Web上运行的Web应用程序后端的“webuser”/“http”服务器或应用服务器的“myappserver”用户)。

当发生这种情况时,我们仍然希望数据库会话知道END用户(例如使用app客户端的实际用户)是用于访问控制还是(与我的兴趣更相关),用于审计/历史触发器能够确定哪个最终用户进行了更改并将最终用户信息记录到审计表中。

请注意,信息是在会话级别设置的,这意味着在该会话中执行的任何插入/更新/删除都可以使用上下文数据,而不会将其传递给每个单独的SQL语句 - 这对于比方说,触发器。

作为一个非常具体的例子,说明你有一个app服务器代表客户端启动数据库会话,你可以在其中插入/更新/删除5个不同表中的行。您希望为这5个表中的每个表都包含审计表,其中包括“哪个最终用户进行了每次更改”信息。

使用上下文数据,您只需使用触发器从应用程序上下文中检索“最终用户”数据,并将其存储为Audit表记录的一部分。在不使用应用程序上下文的情况下,您需要(1)将“最终用户”列添加到这5个表中的每一个(而不是仅审核表)和(2)将您的应用服务器更改为插入或更新set-set应用程序服务器发出的每个SQL语句中该列的值。哦,如果你删除一行,这甚至都不知道如何做到这一点。

2 个答案:

答案 0 :(得分:5)

Oracle有几种不同的方法来实现这一目标。首先,你有DBMS_APPLICATION_INFO package。虽然您可以使用它来设置任意上下文信息,但它通常用于跟踪应用程序。您通常会将模块设置为应用程序的名称,并将操作设置为特定业务流程的描述。然后,您可以从V $ SESSION引用此信息,并通过V $ SESSION_LONGOPS监视长时间运行的操作。

Oracle还可以创建a database object called a context。这是一种更灵活的方式来填充会话级上下文。您可以创建新上下文,然后在该上下文中创建您想要的任何属性。并且您的所有代码都可以简单地引用上下文。例如

SQL> create context my_ctx
  2    using pkg_ctx;

Context created.

SQL> create package pkg_ctx
  2  as
  3    procedure set_context;
  4  end;
  5  /

Package created.

SQL> create or replace package body pkg_ctx
  2  as
  3    procedure set_context
  4    as
  5    begin
  6      dbms_session.set_context( 'MY_CTX', 'USERNAME', 'Justin Cave' );
  7    end;
  8  end;
  9  /

Package body created.

SQL> exec pkg_ctx.set_context;

PL/SQL procedure successfully completed.

SQL> select sys_context( 'MY_CTX', 'USERNAME' )
  2    from dual;

SYS_CONTEXT('MY_CTX','USERNAME')
-------------------------------------------------------------------------------
Justin Cave

答案 1 :(得分:2)

对于PostgreSQL,您可以创建一个自定义变量类,这是postgresql.conf中的配置设置。像这样:

custom_variable_classes = 'myvars'

(如果我没有记错的话,设置此项需要重启服务器)

现在从SQL到您可以通过以下方式读取和写入:

set myvars.some_flag = 'true';
select current_setting('myvars.some_flag');

请注意,您可以“动态”定义所有前缀为myvars的新“变量”。各个值不需要在postgresql.conf

中声明

最初这是用于附加模块,以允许定义自定义配置选项,因此它稍微滥用了该功能,但它应该可以工作。