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   |/

Sun, 25 Jul 1999 10:18:24 +1000
Philip Warner <pjw@rhyme.com.au>
Re: [HACKERS] Re: [SQL] inserts/updates problem under
  stressing !
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

Mon, 26 Jul 1999 10:50:28 +0800
Vadim Mikheev <vadim@krs.ru>
Re: [HACKERS] Re: [SQL] inserts/updates problem understressing !
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


Mon, 26 Jul 1999 10:28:57 +0400 (MSD)
Oleg Bartunov <oleg@sai.msu.su>
Re: [HACKERS] Re: [SQL] inserts/updates problem understressing !