oracle 查询 - ORA-01652: 无法扩展临时段,但仅限于某些版本的 sql*plus

发布于 2024-09-28 02:54:00 字数 1016 浏览 9 评论 0原文

这一点让我相当困惑。我编写了一个查询,该查询在我的开发客户端上运行良好,但在生产客户端上失败,并出现错误“ORA-01652:无法扩展临时段......”。在这两种情况下,数据库和用户是相同的。在我的开发机器 (MS Windows) 上,我安装了 SQL*PLUS(版本 9.0.1.4.0)和 Toad 9.0(均使用 oci.dll 版本 9.0.4.0.1)。两者都运行代码没有错误。

但是,当我在不同的计算机上使用相同的用户名/密码针对同一个数据库运行同一个文件时,这次版本 10.2.0.4.0(来自 10.2.0.4-1 Oracle 即时客户端)出现错误。

它确实会重复发生。

不幸的是,我对数据库上的字典视图的访问权限有限,该数据库设置为只读(甚至无法获得解释计划!)。

我尝试通过调整查询来解决这个问题(我怀疑有一个很大的临时结果集,随后被修剪),但没有设法改变任一客户端的行为。

可能会在导致问题的计算机上部署不同版本的客户端 - 但目前看起来像是降级到以前的版本。

有什么想法吗?

TIA

更新

根据下面加里的回答,我查看了 glogin.sql 脚本 - 唯一的区别是“SET SQLPLUSCOMPATIBILITY 8.1.7”存在于工作客户端上,但在失败客户端上不存在 - 但添加它并没有解决问题。

我也尝试过

alter session set workarea_size_policy=manual;
alter session set hash_area_size=1048576000;

,但

alter session set sort_area_size=1048576000;

没有成功:(

更新 2

我设法找到了相同的行为,这次是与 Oracle 8i 后端对话。在这种情况下,数据库是 RW。这使我能够确认不同的客户端是,正如我怀疑的那样,但为什么???

查看“显示参数”的输出,两个客户端都报告了完全相同的设置!

This one has me rather confused. I've written a query which runs fine from my development client but fails on the production client with error "ORA-01652: unable to extend temp segment by....". In both instances, the database and user is the same. On my development machine (MS Windows) I've got SQL*PLUS (Release 9.0.1.4.0) and Toad 9.0 (both using version 9.0.4.0.1 of the oci.dll). Both run the code without errors.

However when I run the same file, against the same database, using the same username/password from a different machine, this time version 10.2.0.4.0 (from the 10.2.0.4-1 Oracle instant client) I get the error.

It does occur reproducibly.

Unfortunately I've only got limited access to the dictionary views on the database which is set up as read-only (can't even get an explain plan!).

I've tried working around the problem by tuning the query (I suspect that there is a large interim result set which is subsequently trimmed down) but have not managed to change the behaviour at either client.

It may be possible to deploy a different version of the client on the machine causing the problems - but currently that looks like downgrading to a previous version.

Any ideas?

TIA

Update

Based on Gary's answer below, I had a look at the glogin.sql scripts - the only difference was that 'SET SQLPLUSCOMPATIBILITY 8.1.7' was present on the working client but absent on failing client - but adding it in did not resolve the problem.

I also tried

alter session set workarea_size_policy=manual;
alter session set hash_area_size=1048576000;

and

alter session set sort_area_size=1048576000;

to no avail :(

Update 2

I managed to find the same behaviour, this time talking to an Oracle 8i backend. In this case the database was RW. That allowed me to confirm that the different clients were, as I suspected, generating different plans. But why????

Looking at the output of 'SHOW PARAMETERS' both clients reported exactly the same settings!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泡沫很甜 2024-10-05 02:54:00

几年前,我开发了一个完全只读的 DR 数据库,甚至 TEMP 表空间也不可写。任何尝试溢出到临时空间的查询都会失败(即使要使用的临时空间非常小)。

如果是相同的情况,如果有一个 login.sql (或 glogin.sql 或登录触发器)执行 ALTER SESSION 来为会话设置更大的 PGA 内存值,和/或更改优化器目标为 FIRST_ROWS。

如果可以,请比较两个客户端的以下结果:

select * from v$parameter
其中 ismodified!= 'FALSE';

另外,对于每个客户端的问题 SQL,请尝试 EXPLAIN PLAN FOR SELECT...
和 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

看看它是否提出了不同的查询计划。

Years ago I worked on a DR database that was fully READONLY, and even the TEMP tablespace wasn't writable. Any query that tried to spill to temp would fail (even if the temp space to be used was pretty trivial).

If this is the same situation, I wouldn't be surprised if there was a login.sql (or glogin.sql or a logon trigger) that does an ALTER SESSION to set larger PGA memory value for the session, and/or changes the optimizer goal to FIRST_ROWS.

If you can, compare the results of the following from both clients:

select * from v$parameter
where ismodified != 'FALSE';

Also from each client for the problem SQL, try EXPLAIN PLAN FOR SELECT...
and SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

See if it is coming up with different query plans.

莫多说 2024-10-05 02:54:00

不是真正的答案 - 但更多信息......

我们本地的 DBA 能够确认 16Gb (!) TEMP 表空间确实正在使用并已填满,但仅限于 Linux 客户端(我能够重新创建从 PHP 进行 oci8 调用时出错)。在 sqlplus 客户端的情况下,我实际上使用完全相同的文件在两个客户端上运行查询(通过 scp 复制,无需文本转换 - 所以行结尾是 CRLF - 即逐字节与在 Windows 客户端上运行的相同) 。

因此,唯一合理的解决方案是两个客户端堆栈导致不同的执行计划!

在负载非常小的 DBMS 上大约同时从两个客户端运行查询会得到相同的结果 - 这意味着两个客户端还为查询生成不同的 sqlid。

(而且 Oracle 也忽略了我的提示 - 我讨厌它这样做)。

Oracle 不应该这样做 - 即使它在将查询呈现给 DBMS 之前对其进行了一些内部修改(这将产生不同的 sqlid),所使用的客户端堆栈对于选择一个查询应该是完全透明的。执行计划 - 这应该只根据查询的内容和 DBMS 的状态而改变。

由于没有看到任何解释计划,问题变得很复杂 - 但是对于要使用这么多临时表空间的查询,它必须在过滤结果集之前执行非常丑陋的连接(至少部分是笛卡尔连接)。添加提示来覆盖它没有效果。因此,我通过将查询拆分为 2 个游标并使用 PL/SQL 进行嵌套查找来解决该问题。这是一个非常丑陋的解决方案,但它解决了我眼前的问题。幸运的是我只需要生成一个文本文件。

为了那些陷入类似困境的人的利益:

BEGIN

DECLARE
CURSOR query_outer IS
    SELECT some_primary_key, some_other_stuff
    FROM atable
    WHERE....

CURSOR query_details (p_some_pk) IS
    SELECT COUNT(*), SUM(avalue)
    FROM btable
    WHERE fk=p_some_pk
    AND....

FOR m IN query_outer
LOOP
    FOR n IN query_details(m.some_primary_key)
    LOOP
        dbms_out.put_line(....);
    END LOOP;
END LOOP;

END;

我使用 Oracle 的次数越多,我就越讨厌它!

Not really an answer - but a bit more information....

Our local DBAs were able to confirm that the 16Gb (!) TEMP tablespace was indeed being used and had filled up, but only from the Linux clients (I was able to recreate the error making an oci8 call from PHP). In the case of the sqlplus client I was actually using exactly the same file to run the query on both clients (copied via scp without text conversion - so line endings were CRLF - i.e. byte for byte the same as was running on the Windows client).

So the only rational solution was that the 2 client stacks were resulting in different execution plans!

Running the query from both clients approx simultaeneously on a DBMS with very little load gave the same result - meaning that the two clients also generated different sqlids for the query.

(and also Oracle was ignoring my hints - I hate when it does that).

There is no way Oracle should be doing this - even if it were doing some internal munging of the query before presenting it to the DBMS (which would give rise to the different sqlids) the client stack used should be totally transparent regarding the choice of an execution plan - this should only ever change based on the content of the query and the state of the DBMS.

The problem was complicated by not being to see any explain plans - but for the query to use up so much temporary tablespace, it had to be doing a very ugly join (at least partially cartesian) before filtering the resultset. Adding hints to override this had no effect. So I resolved the problem by splitting the query into 2 cursors and doing a nested lookup using PL/SQL. A very ugly solution, but it solved my immediate problem. Fortunately I just need to generate a text file.

For the benefit of anyone finding themselves in a similar pickle:

BEGIN

DECLARE
CURSOR query_outer IS
    SELECT some_primary_key, some_other_stuff
    FROM atable
    WHERE....

CURSOR query_details (p_some_pk) IS
    SELECT COUNT(*), SUM(avalue)
    FROM btable
    WHERE fk=p_some_pk
    AND....

FOR m IN query_outer
LOOP
    FOR n IN query_details(m.some_primary_key)
    LOOP
        dbms_out.put_line(....);
    END LOOP;
END LOOP;

END;

The more I use Oracle, the more I hate it!

梦回梦里 2024-10-05 02:54:00

更多信息 - 我在连接到不同的数据库时遇到了同样的问题 - 这次是 Oracle 8i。我可以获得解释计划。

虽然在这种情况下,查询在两个客户端上完成,但从 Linux sql*plus 10.2.0.4.0 与 WinXP sql*plus 8.0.6.0 运行的时间要长 50%

正如我怀疑的那样,计划是不同的 - 但两者都使用默认值客户端上的设置,两者都使用相同的优化器模式。似乎认为从 Linux 客户端生成的计划比从 XP 客户端生成的计划成本更低(尽管运行时间确实更长)。优化器如何修剪潜在计划的搜索路径?

A bit more information - I've run into the same problem connecting to a different database - this time an Oracle 8i. And I can get EXPLAIN plans.

Although in this case the query completed on both clients, it took 50% longer running from Linux sql*plus 10.2.0.4.0 vs WinXP sql*plus 8.0.6.0

As I suspected, the plans are different - but both are using the default settings on the client, both are using the same optimizer mode. It seems to think the plan generated from the Linux client has a lower cost than that from the XP client (although it does take longer to run). How does the optimizer prune the search path for potential plans?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文