Thread: 100% CPU at concurent access

100% CPU at concurent access

From
"Sabin Coanda"
Date:
Hi there,

I'm trying to solve the concurrent access in my database, but I found some 
problems.

I use "PostgreSQL 8.2.4 on i686-pc-mingw32, compiled by GCC gcc.exe (GCC) 
3.4.2 (mingw-special)";

I create the following scenario:
- use an empty database
- create the following table:
               CREATE TABLE "TestTable"               (                 "ID" integer NOT NULL,
CONSTRAINT"TestTable_pkey" PRIMARY KEY ("ID")               )               WITHOUT OIDS;               ALTER TABLE
"TestTable"OWNER TO postgres;
 

- add a row in the table with
               INSERT INTO "TestTable" VALUES ( 1000 );

- create the following functions:
               CREATE OR REPLACE FUNCTION "TestProcInner"()                 RETURNS integer AS               $BODY$
         DECLARE                       Loops int4 = 10;               BEGIN                       FOR i IN 0..Loops
LOOP                              RAISE NOTICE '%',i;                               UPDATE "TestTable" SET "ID" = i;
                          PERFORM pg_sleep(1);                       END LOOP;
 
                       RAISE NOTICE 'SUCCEEDED';                       RETURN 0;
               EXCEPTION                   WHEN serialization_failure THEN                       RAISE NOTICE
'FAILED';
                       RETURN 1;               END;               $BODY$                 LANGUAGE 'plpgsql' VOLATILE;
           ALTER FUNCTION "TestProcInner"() OWNER TO postgres;
 
       and
               CREATE OR REPLACE FUNCTION "TestProcOuter"()                 RETURNS integer AS               $BODY$
         DECLARE                       Loops int4 := 1;               BEGIN                       LOOP
            RAISE NOTICE 'TestProcOuter: % loop', Loops;                               IF 0 = "TestProcInner"() THEN
                                  EXIT; -- LOOP                               END IF;
Loops= Loops + 1;                       END LOOP;
 
                       RETURN 0;               END;               $BODY$                 LANGUAGE 'plpgsql' VOLATILE;
           ALTER FUNCTION "TestProcOuter"() OWNER TO postgres;
 


I use the following procedure to check when the concurrency access occures:
- open two query windows in pgAdmin
- add the following script in the both windows:
               BEGIN TRANSACTION;               SELECT "TestProcInner"();               COMMIT;

- run the script in the 1st window
- run the script in the 2nd window
- check the results:       - the script in the 1st window commit the transaction               and write the log
message'SUCCEEDED'       - the script from the 2nd window catch an exception               and write the log message
'FAILED'


Then I try to use the following procedure to catch the concurrency access       occurence and retry until both scripts
succeed:
- open two query windows in pgAdmin
- add the following script in the both windows:
               BEGIN TRANSACTION;               SELECT "TestProcOuter"();               COMMIT;

- run the script in the 1st window
- run the script in the 2nd window
- the Postgres begins to CONSUME 100% CPU, and LOCKS until I cancel the 
connection       from other pgAdmin session
- after a few second the first window finishes with 'SUCCEEDED'
- the second window writes:
               ERROR: canceling statement due to user request

Could somebody tell me why the procedure doesn't work and the CPU is used 
100%, please ?

TIA,
Sabin






Re: 100% CPU at concurent access

From
Tom Lane
Date:
"Sabin Coanda" <sabin.coanda@deuromedia.ro> writes:
> Then I try to use the following procedure to catch the concurrency access
>         occurence and retry until both scripts succeed:

What makes you think they ever will succeed?  Once one of these guys has
hit a failure, you've got a tight loop of retrying the same command and
getting the same failure.
        regards, tom lane


Re: 100% CPU at concurent access

From
"Sabin Coanda"
Date:
Hi Tom,

Well, I thought the connection with the failed transaction checks in a loop 
until the succeeded transaction will finish, and then it will succeeded as 
well.

However, would you suggest me a code for "TestProcOuter" that works and 
fulfils my desire, please ? :)


Thanx,
Sabin 




Re: 100% CPU at concurent access

From
"Sabin Coanda"
Date:
I find the problem is in my outer procedure, because it has no sleep there, 
and I change it calling pg_sleep:

-- Function: "TestProcOuter"()

-- DROP FUNCTION "TestProcOuter"();

CREATE OR REPLACE FUNCTION "TestProcOuter"() RETURNS integer AS
$BODY$
DECLARE       Loops int4 := 1;
BEGIN       LOOP               RAISE NOTICE 'TestProcOuter: % loop', Loops;               IF 0 = "TestProcInner"() THEN
                     EXIT; -- LOOP               END IF;               Loops = Loops + 1;               PERFORM
pg_sleep(4);      END LOOP;
 
       RETURN 0;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION "TestProcOuter"() OWNER TO postgres;

With this change, I found the first session succeeds, the CPU is not rised 
anymore, but the second session doesn't succeed even after the first one 
finish successfully.

It fails forever.

Why ? What have I make to succeed ?

TIA,
Sabin