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

Поиск
Список
Период
Сортировка
От Philip Warner
Тема Re: [HACKERS] Re: [SQL] inserts/updates problem under stressing !
Дата
Msg-id 3.0.5.32.19990725101824.00b92c50@mail.rhyme.com.au
обсуждение исходный текст
Список pgsql-hackers
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   |/


В списке pgsql-hackers по дате отправления:

Предыдущее
От: Donny Ryan Chong
Дата:
Сообщение: Please help re backend message type 0x50
Следующее
От: Michael Meskes
Дата:
Сообщение: 6.5.2