I searched for a long time for a response on how correctly  use the database
lock feature  to create a job distribution system. Also I hate programs that
pools databases every few seconds. Than I noticed that postgresql have a
notify feature that inform clients when a table change. Beautiful!! why not
to use it?
It also works with db server behind firewalls because connection is
initiated from the client.

I think that the correct method to use is described by tom lane in this mail

http://archives.postgresql.org/pgsql-general/2003-05/msg00351.php


First of this mail I used this method:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=002b01c2d6ca%24ac
ceff60%240100a8c0%40kodunet.ee&rnum=3&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3D
ISO-8859-1%26q%3D%2522select%2Bfor%2Bupdate%2522%2B%2B%252B%2522limit%2B1%25
22%26meta%3Dgroup%253Dcomp.databases.postgresql.*


Every concurrent process listen for a notify on a working table.
A new job arrives  on a writer table, and is copied by a trigger on a
working table as described by tom lane and others. Also clients are informed
of table change with a notify, so you have not to poll database.

At this point every clients make a select of a new record, and simply try to
update this record.
I notice that  after an update I can query if (atoi(PQcmdTuples(res)) !=0)

And see if it  returns a positive value I  can process the record.


Now what is the difference between this method

////////////////////////////////////////////////////////////////////////////
My poor method

1 )  select id from readertable where  owner = 0 limit 1

2)  update readertable set owner = $me where (id = $id and owner=0);


3)  if (atoi(PQcmdTuples(res)) !=0)        then process record


 and  method described by tom lane ?
///////////////////////////////////////////////////////////////////

--------------------------------------------------
Tom's Lane method

1. When idle, you try to reserve a job like so:

        BEGIN;
        SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
        SELECT job_id, ... FROM job_table
            WHERE processor_id = 0 LIMIT 1 FOR UPDATE;

The SELECT has three possible outcomes:

2: One row is returned.  You do

        UPDATE job_table SET processor_id = $me
            WHERE job_id = $jobid;
        COMMIT;

and then go about executing the job.  When done, delete the row from
job_table and try to get another one.

2b: No row is returned: no jobs are pending.  Commit your transaction,
sleep for an appropriate delay period, and try again.

2c: You get a "can't serialize" failure .........

-----------------------------------------------

Multiple  concurrent updates  on a table can generate a table lock so that
clients must wait for a long time ?
Making only 1  update is  the correct solution , but who can explain this ?
And what exactly do select for update?
Suppose now that many jobs are sumbitted in the same time.
Now with the second method  different jobs are selected by different clients
with only 1 select ?
Why postgresql does not support update table LIMIT 1 ?








---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to