Oracle SQL 会话的生命周期是多少?

What is the lifecycle of a Oracle SQL session?

我在 Oracle SQL 服务器中遇到了全局临时 table 的概念。根据 tutorial on global temporary tables:

The data in a global temporary table is private, such that data inserted by a session can only be accessed by that session.

我相信这可能允许以下情况:客户端启动存储过程两次,每次都预先填充全局临时 table 数据供 sp 处理。这两个计算不会相互干扰,因为每个计算都只能看到自己的数据,而不是像常规 table.

那样共享数据。

但是,这完全取决于 会话 的构成以及开始和结束的时间。

根据 Oracle Database Concepts Glossary:

Session: A logical entity in the database instance memory that represents the state of a current user login to a database. A single connection can have 0, 1, or more sessions established on it.

Connection: Communication pathway between a client process and an Oracle database instance.

这并没有消除我所有的困惑,所以这是我的具体问题:

我的应用程序在其整个生命周期内保持与 Oracle SQL 服务器的单一连接。它在同一个连接上连续执行多个 SQL commands/queries,这些查询中的每一个都是它自己的会话,它们会共享一个会话,还是不是简单地回答?

考虑这个伪代码:

Command c1 = new Command("insert into TMP_TABLE (FOO) values ('TEST')");
Command c2 = new Command("select FOO from TMP_TABLE");

c1.Execute();
foreach (var value in c2.Query().Select("FOO"))
{
    print(value);
}

我的应用程序中有 运行 以上内容,正如预期的那样,命令 c2 返回零结果。我认为这意味着每个查询都构成了自己的会话,这正是我正在寻找的。但是我可以依靠它吗?

Oracle 在 COMMIT/ROLLBACK 操作中清除 TEMPORARY TABLE 内容。

因此,如果您的命令 class 在命令后发出 COMMIT,它也会清除 temp table 和 next 命令中的数据,看不到任何数据内容.

我不知道您的应用程序是否在调用之间保持 Oracle 会话,但无论哪种方式,您都需要注意假设全局临时 table (GTT) 在第二次调用时为空。因为如果它每次都获得一个 "new" 会话,那么这可能真正意味着您正在从连接池中获取一个空闲会话。该会话的前一个用户(可能是您)可能已经为该会话填充了 GTT。我发现在使用 Oracle Application Express (APEX) 时就是这种情况,它是一个基于 HTTP 的应用程序框架。

您需要调用一个使用 GTT 的 Oracle 存储过程,然后截断(清空)它(and/or 在使用前截断它)以确保每次都获得一个干净的状态。

What is the lifecycle of a Oracle SQL session?

会话是一个逻辑实体,从您的应用程序代码连接到数据库到断开连接期间一直存在。

会话独立于支持它们的物理(基于资源的)实体,例如连接、服务器进程、网络连接等

在最简单的(也是最常见的,imo)配置中(即 "dedicated server"),逻辑会话与物理连接和服务器进程之间存在一对一的关系。在支持大量用户的更高级配置中,物理资源(连接、进程、网络资源)可以在多个会话之间共享 by/multiplexed。

I have run the above in my application, and as expected, the command c2 returned zero results. I take this to mean that each query constitutes its own session

除非您的应用程序代码断开连接或closing/releasing它在调用之间的连接,否则几乎可以肯定不是这种情况。

可以使用两个选项创建全局临时表:ON COMMIT DELETE ROWSON COMMIT PRESERVE ROWS

第一个将导致所有 GTT 数据在 commitrollback 时被删除。第二个将导致所有 GTT 数据在整个会话中持续存在。

如果您不使用 ON COMMIT DELETE ROWS,那么您应该而不是假定 GTT 在给定调用开始时为空。如果您要求 GTT 在程序开始时为空,则必须在程序开始时(或最后)DELETE FROM 您的 GTT(或 TRUNCATE 它)。

请注意,即使有此限制(即,必须自己在会话中清空 GTT),全局临时表仍然有用,因为它们仍然可以保护一个会话不看到另一个会话的数据。与常规表相比,它们写入的重做也更少,尤其是在 12.1 及更高版本中。事实上,从 Oracle 12.1 开始,它们根本不需要写入任何重做,这使得它们在只读和备用数据库中非常有用。

一边...

I have run the above in my application, and as expected, the command c2 returned zero results

为了使这个有意义,您的 GTT 必须是使用 ON COMMIT DELETE ROWS 创建的,并且您的应用程序代码启用了某种 "autocommit" 功能,它会在每个 Command.Execute() 之后自动提交.否则你就是misinterpreting/misreporting你的测试结果。

问题:"My application maintains a single connection to an Oracle SQL server throughout its lifetime. It executes multiple SQL commands/queries on that same connection consecutively, will each of these queries be its own session, will they share a session, or is it not that simply answered?"

如果这正是您描述的方式,那么每个查询都是 运行 在它自己的 CURSOR 而不是会话中。如果您 运行 跟踪您的会话并查看原始跟踪文件,您将看到像 PARSING IN CURSOR 这样的部分,其中您的 SQL 被解析并检查语法和权限,然后 EXEC 在服务器上执行的位置,然后是 FETCH 将结果集提取到客户端的位置,以及 CLOSE 关闭游标的位置。如果您的查询已完成,您的游标将隐式关闭;然而,使用 PL/SQL 和游标编程,您可以 control/open/close 您的游标明确。隐式游标可以重复使用,因为 Oracle 在内部为每个游标分配了一个编号。即使您打开单个 SQL*Plus 连接和 运行 单个查询,oracle 也会为其分配一个游标。

示例:

PARSING IN CURSOR #18446744071393882224 len=51 dep=2 uid=63403 oct=3 lid=63403 tim=29425147118918 hv=682153908 ad='3e6edfd80' sqlid='344kggsnajpxn'
SELECT "BDD_EXTERNALBATCH_ID_SEQ".NEXTVAL FROM DUAL
END OF STMT
EXEC #18446744071393882224:c=73,e=73,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,plh=1849910378,tim=29425147118915
FETCH #18446744071393882224:c=9161,e=9402,p=0,cr=2,cu=3,mis=0,r=1,dep=2,og=1,plh=1849910378,tim=29425147128989
CLOSE #18446744071393882224:c=9,e=8,dep=2,type=3,tim=29425147129472

现在,如果您通过 Weblogic 建立连接池 - 那么您将打开许多在连接池中定义的 SESSIONS,并且每个查询都会进入由 Weblogic 处理的相应会话。有时 Weblogic 会增大或缩小池(在配置参数范围内),当池增大时您将创建更多会话。

您也可以 运行 如果您选择这样做,每个查询都在其自己的会话中,但这是一个非常糟糕的主意,并且出于性能原因无法扩展。最好 运行 在会话范围内或通过存储过程和包在服务器上尽可能多地查询和 DML。

关于 GTT(全局临时表)- 它们在您的会话中使用,并在您的会话关闭时释放。除了 GTT 的明显用途之外,我们还使用它们将某些 类 用户转移到不同的临时段(通过巧妙地使用视图和触发器),因为在繁忙的系统中,临时段的竞争可能非常激烈段。