0

There is a multithreaded application executing some PL/pgsql function. That function produces record inserts to a critically important resource( table ). Also it executes some select/update/etc operations while executing.

The issue is, sometimes we face duplicate( 2-3 ) records each one passed to the function in a parallel thread. And they all are inserted into table as a function execution result, while they should not.

It happens, because both transactions are executed in parallel, and have no idea that the same record is being prepared to insert in a parallel transaction.

The table is critically important and all kinds of LOCK TABLE are extremely not welcomed (LOCK FOR SHARE MODE meanwhile gave as some useful experience).

So, the question is, is there any best practice how to organize PL/pgsql function working with a critical resource (table) to be executed by multithreaded app and producing no harmful locks on this resource?

PS. I know, that some thread partinioning by record.ID in the app is a possible solution. But I.m interested in a PL/pgsql solution first of all.

4
  • Is it safe to assume that you either do not have a Primary/Unique key, or that by "duplicates", you mean attributes other than the Primary/Unique key? Locking or serialized access are the only ways to ensure the uniqueness of your entries, or at least that I can think of. A resource available in Postgresql 9.2+ is Serializable Snapshot isolation (wiki.postgresql.org/wiki/SSI) but that might be a bit heavyweight for your needs. Commented Aug 1, 2013 at 14:43
  • We have a PK constraint, but it is a logical duplicateness, not a straightforward field-by-field matching. And Serializable Isolation level is not a acceptable solution for us: it produces serialization access denies for parallel transaction that can unpredictably affect application behavior. Thanks for advice anyway! Commented Aug 1, 2013 at 15:02
  • If your primary key allows duplicates, it's not a primary key is it? What precisely do you mean by duplicateness. Commented Aug 1, 2013 at 15:27
  • Well @Richard Huxton you are right about that. Building the Unique index is a possible solution no doubt. But im looking for more flexible solution (pg_advisory_lock seems to be the best candidate at the moment) Commented Aug 1, 2013 at 15:59

1 Answer 1

2

Sometimes you can use a advisory locks - http://www.postgresql.org/docs/current/static/explicit-locking.html .With these locks some subset of numbers. I used it for synchronization of parallel inserts with success.

Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately advisory_lock cant do what I would like him to do. Actually, expected to find a database engine module, that would allow me to declare some lock rule like 'select do_lock(*) from resource_tbl where id between 1 and 100' that would mean database will not allow to insert new records with id from interval from 1 to 100. All existing techniques, as far as I realised, allow me to lock some already existing records only. Anyway, I came to the conclusions I needed, thanks for paying attention to the question!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.