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

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

From
Philip Warner
Date:
At 12:29 24/07/99 -0400, you wrote:
>Oleg Bartunov <oleg@sai.msu.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   |/


Re: [HACKERS] Re: [SQL] inserts/updates problem understressing !

From
Vadim Mikheev
Date:
Philip Warner wrote:
> 
> 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:

But if there was no record then nothing will be locked...
Without ability to read dirty data LOCK is the only way.

...

> 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It doesn't.

> start a TX in the procedure, or prior to valling it.

Vadim


Re: [HACKERS] Re: [SQL] inserts/updates problem understressing !

From
Oleg Bartunov
Date:
On Mon, 26 Jul 1999, Vadim Mikheev wrote:

> Date: Mon, 26 Jul 1999 10:50:28 +0800
> From: Vadim Mikheev <vadim@krs.ru>
> To: Philip Warner <pjw@rhyme.com.au>
> Cc: pgsql-hackers@postgreSQL.org, pgsql-sql@postgreSQL.org,
>     Oleg Bartunov <oleg@sai.msu.su>
> Subject: Re: [HACKERS] Re: [SQL] inserts/updates problem understressing !
> 
> Philip Warner wrote:
> > 
> > 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:
> 
> But if there was no record then nothing will be locked...
> Without ability to read dirty data LOCK is the only way.
> 

I agree, no data, no locking.

> ...
> 
> > 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
>                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> It doesn't.
> 
> > start a TX in the procedure, or prior to valling it.

How do I start a TX in the procedure ? Is't possible ?
I don't understand this because a procedure must return something, so 
there're no point where to end a TX.
Oleg
> 
> Vadim
> 

_____________________________________________________________
Oleg Bartunov, sci.researcher, hostmaster of AstroNet,
Sternberg Astronomical Institute, Moscow University (Russia)
Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/
phone: +007(095)939-16-83, +007(095)939-23-83