Re: [HACKERS] Re: [SQL] inserts/updates problem under stressing !

From: Philip Warner <pjw(at)rhyme(dot)com(dot)au>
To: pgsql-hackers(at)postgreSQL(dot)org, pgsql-sql(at)postgreSQL(dot)org
Cc: Oleg Bartunov <oleg(at)sai(dot)msu(dot)su>
Subject: Re: [HACKERS] Re: [SQL] inserts/updates problem under stressing !
Date: 1999-07-25 00:18:24
Message-ID: 3.0.5.32.19990725101824.00b92c50@mail.rhyme.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-sql

At 12:29 24/07/99 -0400, you wrote:
>Oleg Bartunov <oleg(at)sai(dot)msu(dot)su> writes:
>> I did some benchmarks of my Web site and notice I lost some hits
>> which I accumulate in postgres (6.5.1) database on Linux 2.0.36 system
>
>> CREATE FUNCTION "acc_hits" (int4) RETURNS int4 AS '
>> Declare
>> keyval Alias For $1;
>> cnt int4;
>> curtime datetime;
>> Begin
>> curtime := ''now'';
>> Select count into cnt from hits where msg_id = keyval;
>> if Not Found then
>> cnt := 1;
>> -- first_access inserted on default, last_access is NULL
>> Insert Into hits (msg_id,count) values (keyval, cnt);
>> else
>> cnt := cnt + 1;
>> Update hits set count = cnt,last_access = curtime where msg_id =
keyval;
>> End If;
>> return cnt;
>> End;
>> ' LANGUAGE 'plpgsql';
>
>I wonder whether this doesn't have a problem with concurrent access:
>
>1. Transaction A does 'Select count into cnt', gets (say) 200.
>2. Transaction B does 'Select count into cnt', gets 200.
>3. Transaction A writes 201 into hits record.
>4. Transaction B writes 201 into hits record.
>
>and variants thereof. (Even if A has already written 201, I don't think
>B will see it until A has committed...)
>
>I am not too clear on MVCC yet, but I think you need "SELECT FOR UPDATE"
>or possibly an explicit lock on the hits table in order to avoid this
>problem. Vadim, any comments?

The usual way around this sort of problem is to update the counter as the
first thing you do in any transaction. This locks the row and prevents any
possible deadlock:

Begin
curtime := ''now'';
update hits set count = count + 1; -- Now have a lock, which causes
other updates to wait.
get diagnostics select processed into numrows;
if numrows == 0 then
cnt := 1;
-- first_access inserted on default, last_access is NULL
Insert Into hits (msg_id,count) values (keyval, cnt);
End If;
return cnt;
End;

The only hassle with this is that the patch to plpgsql for 'get
diagnostics' is not yet applied (I may not have mailed it yet...), and I am
not sure if plpgsql starts a new TX for each statment - if so, you need to
start a TX in the procedure, or prior to valling it.


----------------------------------------------------------------
Philip Warner | __---_____
Albatross Consulting Pty. Ltd. |----/ - \
(A.C.N. 008 659 498) | /(@) ______---_
Tel: +61-03-5367 7422 | _________ \
Fax: +61-03-5367 7430 | ___________ |
Http://www.rhyme.com.au | / \|
| --________--
PGP key available upon request, | /
and from pgp5.ai.mit.edu:11371 |/

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Herouth Maoz 1999-07-25 12:40:48 Re: [SQL] database design SQL prob.
Previous Message Bruce Momjian 1999-07-24 20:15:19 Re: [HACKERS] RE: [INTERFACES] Re: SSL patch

Browse pgsql-sql by date

  From Date Subject
Next Message Herouth Maoz 1999-07-25 12:40:48 Re: [SQL] database design SQL prob.
Previous Message Tom Lane 1999-07-24 23:38:02 Re: [SQL] Views Readonly Still?