atomic multi-threaded upsert

From: "Mikhail V(dot) Puzanov" <misha(dot)puzanov(at)gmail(dot)com>
To: pgsql-sql(at)postgresql(dot)org
Subject: atomic multi-threaded upsert
Date: 2010-11-24 20:16:59
Message-ID: 4CED72BB.3070905@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-sql

Hi, All

I'm trying to make a kind of upsert for the following table:

CREATE TABLE sequences (
section VARCHAR( 50 ) NOT NULL,
name VARCHAR( 50 ) NOT NULL,
counter BIGINT NOT NULL
);

CREATE UNIQUE INDEX IDX_SEQUENCES_SN ON sequences(section, name);

Next, I execute the following two queries for that table:

-- increment and get the counter if exists
UPDATE sequences SET counter = counter + 1
WHERE section = 'testSection' AND name = 'testKey'
RETURNING counter;

-- insert new counter if not exists
INSERT INTO sequences ( section, name, counter )
SELECT 'testSection', 'testKey', 0
WHERE NOT EXISTS (
SELECT * FROM sequences
WHERE section = 'testSection' AND name = 'testKey'
);

It works OK when executed in single thread.

When such pairs of queries are executed in parallel (3-10 threads,
1 JDBC connection for each thread, with autoCommit set),
occasionally I get the following error:

ERROR: duplicate key value violates unique constraint "idx_sequences_sn"

1) That looks weird actually, should the INSERT ... NOT EXISTS (...) be
executed
in atomic fashion? Also, AFAIK, UNIQUE INDEX locks rows before
insert (or not?).
Can it be related to JDBC?
Or it's the result of MVCC conflict resolution?

2) Are there some patterns for such kind of task?

Thanks.

Responses

Browse pgsql-sql by date

  From Date Subject
Next Message Louis-David Mitterrand 2010-11-24 20:53:16 Re: "compressing" consecutive values into one
Previous Message bricklen 2010-11-23 18:19:45 Re: "compressing" consecutive values into one