Skip to Main Content
  • Questions
  • ORA-06500: PL/SQL: storage error use sql collection

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Jimmy.

Asked: January 08, 2005 - 6:49 pm UTC

Last updated: November 14, 2008 - 4:36 pm UTC

Version: 9.2.0.4.0

Viewed 10K+ times! This question is

You Asked

Hello Tom,

The mentioned error appears when using a SQL collections which this cradle in a stored type which I define next:

CREATE OR REPLACE TYPE R235_TYPE AS OBJECT
(
C_1 NUMBER(3),
C_2 VARCHAR2(2),
C_3 NUMBER(10),
C_4 NUMBER(2),
C_5 VARCHAR2(50),
C_6 VARCHAR2(50),
C_7 NUMBER(4),
C_8 NUMBER(14,4),
C_9 NUMBER(14,4),
C_10 NUMBER(14,4),
C_11 NUMBER(14,4),
C_13 NUMBER(14,4),
C_14 NUMBER(14,4),
C_15 NUMBER(14,4),
C_16 NUMBER(14,4),
C_17 NUMBER(14,4),
C_18 NUMBER(14,4),
C_19 NUMBER(14,4),
C_20 NUMBER(1)
);

CREATE OR REPLACE TYPE R235_TABLE AS TABLE OF R235_TYPE;

A report is due to generate that has information of several conditions (not necessarily sentences SQL), which I do is to fill the collection and soon it made a cursor on her to recover the information of the way which I want and to generate the report...

When it loads registry 1114931 in the collection appears the ERROR: ORA-06500: PL/SQL: storage error

Collections SQL have limits of record number?

How it could solve this problem or of which another way could do it?

Thanks,

and Tom said...

You think it is reasonable to stash over 1 million things in memory in an array.

ouch.

what you have basically done is "run out of that which you may run out of". namely: Memory.

Maybe you need to read about pipelined functions if you truly and utterly believe you cannot do it in sql. In that fashion instead of trying to stuff over 1 million big records into RAM (i bet the machine was running in a spectacular fashion in the minutes leading upto your ora-6500...) you return them to the client for processing one by one as they are prepared. Search for pipelined on this site.

Or, maybe you need to utilize a global temporary table, which will buffer records in the cache until there is insufficient space and then get them onto disk. search for "global temporary table" on this site.


But, more than a couple hundred/thousands records in memory? Not in any language, not in any normal situation, never for a report.

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

ORA-06500 error

Arti Mehta, March 03, 2005 - 12:11 pm UTC

I got the error on trying to execute procedure. I am very new to Oracle. My error is as follow:
---Command executed---
Begin
EXECUTE SCHEDULE_PROCEDURE_DAILY('CDSS_Proc_ClearTrackTable', '04-MAR-2005',' 05:00 AM')
end
/
----Error-----
ERROR at line 2:

ORA-06550: line 2, column 9:
PLS-00103: Encountered the symbol "SCHEDULE_PROCEDURE_DAILY" when expecting one
of the following:
:= . ( @ % ; immediate
The symbol ":=" was substituted for "SCHEDULE_PROCEDURE_DAILY" to continue.
ORA-06550: line 3, column 1:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
. ( * % & = - + ; < / > at in is mod not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like
between ||

Tom Kyte
March 03, 2005 - 12:17 pm UTC

execute is not a plsql command.

execute is a sqlplus short cut 

SQL> exec p

is just a sqlplus shortcut for


SQL> begin
  2     p;
  3  end;
  4  /


remove the word execute (on your way to otn.oracle.com to pick up the documentation which is all there so you can learn plsql and sql and how oracle works....) 

PL/SQL: storage error: ORA-06500, ORA-04030, ORA-07324, SVR4 Error

Pmenon, February 02, 2006 - 10:48 pm UTC

Hi Tom,

I have got a set of errors while executing a PL/SQL package.

Environment
=============
Oracle7 Server Release 7.3.4.5.0 - Production
PL/SQL Release 2.3.4.5.0 &#8211; Production

System = SunOS
Release = 5.6
Machine = sun4u
NumCPU = 24
RAM = 24 GB

Error Message
==============
ERROR while trying to load RTX Records for customer :1228313 : ORA-06500: PL/SQL: storage error
ORA-04030: out of process memory when trying to allocate 2416 bytes (callheap,plbtn: outlined leaf data)
ORA-07324: smpall: malloc error while allocating pga.
SVR4 Error: 12: Not enough space
Number of calls loaded :752909 in 77784 milli seconds
FROM IVDC_MAIN while processing customer :1228313:ORA-04030: out of process memory when trying to allocate 25600 bytes (cursor work he,KKRH Bit vector)
ORA-07324: smpall: malloc error while allocating pga.
SVR4 Error: 12: Not enough space
ORA-04030: out of process memory when trying to allocate 2416 bytes (callheap,plbtn: outlined leaf data)
ORA-07324: smpall: malloc error while allocating pga.
SVR4 Error: 12: Not enough space
ERROR : While calculating discount for Customer ::1228313


This has happened when I am trying to process about 800000 records. These are telephone call records.

The program goes this way..

Read customer
-- Create a cursor for customer calls
---- Use For Loop to load calls into Array (PL/SQL table)
------ Process...
Repeat for next customer.

I understand from your first comment that loading these many records in memory is not a good idea in the first place. Any alternates?

One way to do this would be to change the program execution.

Read customer
-- Create a cursor for customer calls (limit to say 10000 records)
---- Use For Loop to load calls into Array (PL/SQL table)
------ Repeat next batch (till all calls are retrieved)
-------- Process...
Repeat for next customer.

We are currently moving to 10G and would like to use features there. What would you recommend? Is my approach to the problem correct? Would BULK COLLECT help here? You could also guide me any part of the documentation. (I read one of your posts which states that PL/SQL in 10g does BULK COLLECT of 100 rows internally)


Tom Kyte
February 03, 2006 - 1:58 pm UTC

don't load records into memory? Make a better algorithm. We used to write programs that could run in a few bytes, then kilobytes then 10s of kilobytes (that was huge...) It can still be done.

Sinan Topuz, September 12, 2008 - 11:16 am UTC

Tom,

8.1.7.4 Standard Edition on Windoze 2000 Server w/ 3G memory & 1.8Ghz XEO CPU.

I have a daily job which checks alert.log for errors and I am getting the following in the alert log because of the job's itself:

Fri Sep 12 09:50:02 2008
Errors in file D:\OraHome\admin\d7i\bdump\d7iSNP9.TRC:
ORA-12012: error on auto execute of job 38066192
ORA-20000: ORA-06500: PL/SQL: storage error
ORA-06512: at "D7IPRD.ALERTLOG_NOTIFICATION", line 90
ORA-06512: at line 1

Fri Sep 12 09:51:04 2008
Thread 1 advanced to log sequence 344031
Current log# 2 seq# 344031 mem# 0: D:\ORAHOME\ORADATA\D7I\REDO02.LOG
Fri Sep 12 09:51:04 2008
ARC1: Beginning to archive log# 1 seq# 344030
ARC1: Completed archiving log# 1 seq# 344030
Fri Sep 12 09:52:18 2008
Errors in file D:\OraHome\admin\d7i\bdump\d7iSNP9.TRC:
ORA-12012: error on auto execute of job 38066192
ORA-20000: ORA-06500: PL/SQL: storage error
ORA-06512: at "D7IPRD.ALERTLOG_NOTIFICATION", line 90
ORA-06512: at line 1


Below is the procedure which is triggered by the job:

CREATE OR REPLACE PROCEDURE AlertLog_notification
AS

R_email  varchar2(2000);
mbody    varchar2(32000);
msubj    varchar2(2000);
l_days   number;
rcount   number;

dfile    SendMailJPkg.ATTACHMENTS_LIST;
l_errstatus number;

TYPE typ1 IS REF CURSOR;
ref_cr    typ1;
SQ        varchar2(5000);
l_user_code dw_lookups.lookup_value%TYPE;

BEGIN

  l_errstatus := 0;

  SQ := 'select lookup_value from dw_lookups where lookup_code = :1';

  -- Get the list of users to be notified
  r_email := ' ';
  OPEN ref_cr FOR SQ using 'N_D7I_ALERTLOG_NOTIFICATION' ;
  LOOP
     FETCH ref_cr INTO l_user_code;
     IF ref_cr%NOTFOUND THEN
        EXIT;
     END IF;
      r_email := r_email || Getperinfo(l_user_code, 'E') || ',';
  END LOOP;

  r_email := trim(r_email);

  IF dw_right(r_email, 1) = ',' THEN
     r_email := substr(r_email, 1, length(r_email)-1);
  END IF;

  mbody := '*****************************************************' || chr(13);
  mbody := mbody || '* THIS IS AN AUTOMATED EMAIL, PLEASE DO NOT REPLY   *' || chr(13);
  mbody := mbody || '*****************************************************' || chr(10) || chr(13);
  mbody := mbody || 'FYI.' || chr(10) || chr(13);

  mbody := mbody || 'Alert log has ERROR(s) in it.' || chr(10) || chr(13);

  rcount := 0;
  -- Check if there any contracts about to expire
  FOR C1 IN ( select * from (
                     select text from d7i_alert_log t where rownum < 100 order by line desc
                 ) where instr(text, 'ORA-') > 0
            ) LOOP

     rcount := rcount + 1;
     mbody := mbody || c1.text  || chr(10) || chr(13);
  END LOOP;

  IF r_email IS NOT NULL
    AND instr(r_email, '@') > 0
    AND rcount > 0 THEN

    msubj := 'Alert log has ERROR(s) in it.';

    l_errstatus := DW_sendemail
        (pcuser        => 'testuser'
        ,pfile         => dfile
        ,psendername   => 'Administrator'
        ,psender       => 'test@***.com'
        ,psubject      => msubj
        ,pRecipient    => r_email
        ,pbody         => mbody );

  END IF;

  EXCEPTION WHEN OTHERS THEN
      raise_application_error(-20000, SQLERRM);

END;


Could you point out which is memory intensive in this code please? I am guessing that it is the function or the view below, but I don't know how I can make this use less resources.

d7i_alert_log is a view that I created again with your help:

CREATE OR REPLACE VIEW D7I_ALERT_LOG AS
SELECT "LINE","TEXT"
FROM Table(Cast(Get_D7I_Alert() As Alert_Type))
/

CREATE OR REPLACE FUNCTION Get_D7I_Alert RETURN Alert_Type IS
  Alert_Tab  Alert_Type := Alert_Type();
  l_file     UTL_FILE.file_type;
  l_line     NUMBER(10) := 1;
  l_text     VARCHAR2(2000);
BEGIN

  l_file := UTL_FILE.fopen('D:\OraHome\admin\d7i\bdump', 'TSTALRT.LOG', 'r');

  BEGIN
    LOOP
      utl_file.get_line(l_file, l_text);
      Alert_Tab.Extend;
      Alert_Tab(Alert_Tab.Last) := Alert_Row_Type(l_line, l_text);
      l_line := l_line + 1;
    END LOOP;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      NULL;
  END;
  UTL_FILE.fclose(l_file);
  RETURN Alert_Tab;
END;


Thanks.
Tom Kyte
September 16, 2008 - 1:44 pm UTC

... EXCEPTION WHEN OTHERS THEN
raise_application_error(-20000, SQLERRM);
....

I will not for the life of me ever understand the "logic" behind that. erase that code and stop doing that - or at least explain clearly why you think it is better than capturing the ACTUAL error code and the ACTUAL line number that the error occurred on? All that when others can achieve is a) hide the ora-xxxxx number from us, b) hide the line number where the error actually happened from us. Eg: it HURTS US a lot, it HELPS US none.


ummm, and how big is your alert log? That seems like an obvious place to look doesn't it?

In order to process errors in the alert log, you only really need the "end of it" - if you were to remember the last time you read the alert log, you could just read and through out records until you hit a timestamp that exceeds the last time you read it - eg: only put into an array relevant bits.

I'll bet your alert log is huge.

ora-6500 and ORA-4030

Atul, November 13, 2008 - 6:13 am UTC

I am getting following error in a concurrent Program which is custom.

ORA-6500 PL/SQL: storage error with ORA-4030

==

I saw package and I could see lot of PL-SQL Tables in the Package.


TYPE v_line_type_type IS TABLE OF VARCHAR2(30);
TYPE v_term_name_type IS TABLE OF VARCHAR2(240);
TYPE v_linked_line_type_type IS TABLE OF VARCHAR2(30);
TYPE v_customer_num_messg_type IS TABLE OF VARCHAR2(240);
TYPE v_invoice_num_i_messg_type IS TABLE OF VARCHAR2(240);
TYPE v_invoice_num_b_messg_type IS TABLE OF VARCHAR2(240);
TYPE v_currency_code_messg_type IS TABLE OF VARCHAR2(240);
TYPE v_salesrep_messg_type IS TABLE OF VARCHAR2(240);
TYPE v_invoice_flag_type IS TABLE OF VARCHAR2(1);


And also I could see BULK COLLECT Statements in the code.




Below are my Database Settings for PGA and SGA

==

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 1G
sga_max_size big integer 1G
sga_target big integer 1G


===

Database version is 10G and OS is Linux.
ulimit for oracle user is below,only stack size is not unlimited all others are unlimited.

==
[oracnv@collin03 tmp]$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
pending signals (-i) 1024
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 16384
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
stack size (kbytes, -s) 10240cpu time (seconds, -t) unlimited
max user processes (-u) 2047
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
====


Could you please help me to resolve this error?
Tom Kyte
November 14, 2008 - 4:36 pm UTC

use less memory.

this is not stack size, this is dynamic (heap) memory. You ran out of process memory.

Your ulimit for that appears to be unlimited - so you exhausted real memory. It is quite easy to do:

declare
type array is table of long index by binary_integer;
l_data array;
begin
loop
l_data(l_data.count+1) := rpad('*',32000,'*');
end loop;
end;
/

will probably do it - the only fix would be "use less memory"

so, look to your code and ask "why would this bit of code use such a large amount of memory - is the developer loading a really unreasonable number of records into memory?"

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library