在 Oracle 内存缓存中长时间存储 PLSQL 存储过程值
Posted
技术标签:
【中文标题】在 Oracle 内存缓存中长时间存储 PLSQL 存储过程值【英文标题】:Storing PLSQL stored-procedure values in Oracle memory caches for extended periods 【发布时间】:2010-06-08 22:52:55 【问题描述】:我正在从 PLSQL 存储过程中收集运行时分析数据。数据是在某些存储过程执行时收集的,但需要在这些过程的多次执行中累积。
为了最大限度地减少开销,我想在数据收集间隔期间将分析数据存储在某个 PLSQL 可访问的 Oracle 内存驻留存储中,然后转储出累积值。数据收集间隔可能是几秒或几小时;可以不跨系统启动存储这些数据。像 Web 服务器中的会话状态这样的东西就可以了。
我有哪些存储此类数据的选择?
我知道的唯一方法是 dbms_sessions 中的上下文:
procedure set_ctx (value in varchar8) as
begin
dbms_session.set_context ( 'Test_Ctx', 'AccumulatedValue', value, NULL, 'ProfilerSessionId' );
end set_ctx;
这可行,但每次更新累积值需要大约 50 微秒(!)。
我希望的是一种使用普通 PLSQL 语句在一些 Oracle 内存中访问/存储值数组的方法,访问时间是对包本地数组进行的数组访问的典型访问时间。
编辑(在了解 PLSQL 包变量的会话生命周期之后):
是否存在生命周期长于“会话”的 PLSQL 可访问变量?我猜想这些变量可能需要同步才能启用来自多个会话的安全更新。奇怪的是,我收集的那种性能数据不会受到这种同步错误的严重伤害,因为性能数据值只是单调增长。同步错误仅仅意味着我们没有捕捉到一点价值增长,我认为这不会损害我正在做的事情。
【问题讨论】:
我不完全理解你,但你能不能不创建一个包并定义包级集合变量,你可以在其中积累你的统计数据。包变量在会话持续时间内持续存在 @joshephj1989:他们有吗?那是好消息。 [写下你的评论作为答案,并从我这里得到一个布朗尼点]。嗯,我想这意味着它们是 session 特定的。 (我正在尝试跨整个系统收集数据,可能有多个会话来来去去,但我愿意保持一个会话打开以累积数据......尽管可能无法跨会话累积数据在特定的包实例中,对吧?) 【参考方案1】:我能想到的唯一方法是拥有一个不断运行和维护内存数据的“侦听器”进程。然后,您的其他进程将通过与侦听器通信来记录信息,例如DBMS_PIPE 或 DBMS_AQ。 DBMS_PIPE 文档中有一个 Pro*C 侦听器进程的示例。
但是,我怀疑这对于调用程序是否比通过自治事务将信息写入表的更简单解决方案更有效。
【讨论】:
【参考方案2】:如何使用具有相当固定内存配置文件的每个会话包,您会定期(每 N 次更新)刷新到数据库(用于您的“所有会话”数据),然后重置。
如果您可以执行插入而不是更新,则锁定的风险应该很低,然后您可以对行使用视图或物化视图来获取累积总数。
或者,如果将其与 Tony 建议的 DBMS_AQ 方法结合使用,您可以保证不会出现锁定 - 将消息放入队列很快,并且您可以将队列链接到在 Oracle 后台执行的 PLSQL 包上的回调线。
【讨论】:
【参考方案3】:我不完全确定你在做什么,但我已经为 PL/SQL 编写了一个详细的日志记录包,它允许通过 PL/SQL 等跟踪执行,计时到毫秒。但是与您自己相关,有一个选项可以记录到内存,即没有使用 PL/SQL 集合的 I/O。换句话说,您可以记录到缓冲区并定期将缓冲区刷新到表中。可从https://sourceforge.net/p/plj-logger/home/ 或http://www.pljumpstart.com/download 获得它
它还有一个额外的优点,就是实现起来非常简单。单个包和支持表等。
【讨论】:
以上是关于在 Oracle 内存缓存中长时间存储 PLSQL 存储过程值的主要内容,如果未能解决你的问题,请参考以下文章
oracle plsql 存储过程错误处理 oracle-6502