Re: Perl function leading to out of memory error - Mailing list pgsql-general
| From | Christian Schröder |
|---|---|
| Subject | Re: Perl function leading to out of memory error |
| Date | |
| Msg-id | 5125087D.8090105@deriva.de Whole thread Raw |
| In response to | Re: Perl function leading to out of memory error (Tom Lane <tgl@sss.pgh.pa.us>) |
| Responses |
Re: Perl function leading to out of memory error
|
| List | pgsql-general |
On 19.02.2013 12:41, Tom Lane wrote:
> Jan Strube <js@deriva.de> writes:
>> we have a Java daemon that´s repeatedly calling a Perl function inside
>> our database (version 9.1.8). The function is called about 200 times per
>> second. While the Java program is running you can watch the memory usage
>> of the postmaster grow continuously until after a few hours we get an
>> out of memory error from Postgres. In the log you see a lot of
>> "ExprContext..." messages.
> I tried to reproduce this, without much success. Can you extract a
> self-contained test case?
after some investigation it seems that the error has to do with a domain
type that we have defined in our database. We have defined the following
helper functions:
CREATE OR REPLACE FUNCTION isin_pz(text) RETURNS integer AS $$
DECLARE c char; s text := ''; l integer; d integer; w integer; sum integer := 0;
BEGIN IF char_length($1) != 11 THEN RETURN null; END IF;
IF substr($1, 1, 2) < 'AA' OR substr($1, 1, 2) > 'ZZ' THEN RETURN null; END IF;
FOR pos IN 1 .. 11 LOOP c := substr($1, pos, 1); IF c >= '0' AND c <= '9' THEN s := s ||
c; ELSE IF c >= 'A' AND c <= 'Z' THEN s := s || to_char(ascii(c) - 55, 'FM99');
ELSE RETURN null; END IF; END IF; END LOOP;
l := char_length(s); FOR pos IN 1 .. l LOOP d := to_number(substr(s, pos, 1), '0'); w :=
((l-pos+1)% 2) + 1; IF w * d >= 10 THEN sum := sum + (w * d) % 10 + 1; ELSE sum :=
sum+ (w * d); END IF; END LOOP;
RETURN (10 - (sum % 10)) % 10;
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION isin_ok(text) RETURNS boolean AS $$
DECLARE pz integer;
BEGIN IF char_length($1) != 12 OR substr($1, 1, 2) < 'AA' OR substr($1,
1, 2) > 'ZZ' THEN RETURN false; END IF;
pz := public.isin_pz(substr($1, 1, 11)); IF pz IS NULL THEN RETURN false; END IF;
RETURN to_char(pz, 'FM9') = substr($1, 12, 1);
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE STRICT;
They are used to define the domain type "isin" as follows:
CREATE DOMAIN isin AS char(12) CHECK (isin_ok(value));
Now we can create our test case. Create the following table:
CREATE TABLE foo (isin char(12) NOT NULL);
And this function:
CREATE OR REPLACE FUNCTION foo(isin char(12)) RETURNS void AS $$
my ($isin) = @_;
my $stmt = spi_prepare(' INSERT INTO foo (isin) VALUES ($1)', 'isin');
spi_exec_prepared($stmt, $isin);
spi_freeplan($stmt);
$$ LANGUAGE plperl VOLATILE STRICT;
If we now repeatedly call this function (e.g. using a Perl script) we
can see the memory consumption rise continuously until the out of memory
error occurs.
Interestingly, if we change the type specification in the call to
"spi_prepare" from "isin" to "char(12)" the problem no longer occurs.
Can you explain this behavior?
Regards,
Christian
--
Deriva GmbH Tel.: +49 551 489500-42
Financial IT and Consulting Fax: +49 551 489500-91
Hans-Böckler-Straße 2 http://www.deriva.de
D-37079 Göttingen
Amtsgericht Göttingen | HRB 3240
Geschäftsführer: Dirk Baule, Christian Schröder
Deriva CA Certificate: http://www.deriva.de/deriva-ca.cer
pgsql-general by date: