Re: Changing the transaction isolation level within - Mailing list pgsql-sql

From Mario Splivalo
Subject Re: Changing the transaction isolation level within
Date
Msg-id 1138353623.8494.20.camel@localhost.localdomain
Whole thread Raw
In response to Re: Changing the transaction isolation level within the stored  (Markus Schaber <schabi@logix-tt.com>)
List pgsql-sql
On Thu, 2006-01-26 at 10:42 +0100, Markus Schaber wrote:

> >>>Is it possible to change the transaction level within the procedure?
> >>No, currently not, the PostgreSQL "stored procedures" really are "stored
> >>functions" that are called inside a query, and thus cannot contain inner
> >>transactions.
> > Is above true for the newly introduced stored procedures? (Above, when
> > mentioning 'stored procedures' I was actualy reffering to 'functions').
> 
> I have to admit that I don't know what "newly introduced stored
> procedures" you're talking about? Is this an 8.2 feature?

And I have to cry 'Why am I not Dumbo, so I could cover myslef with me
ears'. I was reffering to the IN/OUT parametar ability for the
functions, and confused them with 'stored procedures' in other RDBMSes.


> PostgreSQL (and e. G. Oracle) use a MVCC system for transactions, that
> doesn't need exclusive locks.

Has nothing to do with a thread, but, even with MVCC you sometimes need
locking. One case is tracking stock by FIFO metod. There, you need to
serialize transactions which take items from the stock, so they're
ordered.

> I suggest you to read "Chapter 12. Concurrency Control" from the
> PostgreSLQ docs.
> 
> Its easy: if you need "read committed" guarantees, then run the entire
> transaction as "read committed". If you need "serializable", then run
> the entire transaction as "serializable". If you need real serialization
> and synchronization of external programs, use LOCK (or take a deep
> breath, redesign your application and use e. G. LISTEN/NOTIFY. Most
> times, the usage of LOCK is a good indicator of misdesign.)

But, I need to control those from the client, right? For some action
that I'd like database to perform I created functions as an interface to
the application. I'd like for database to take care about transactions
and everything. So, there is one 'external' function that client
application calls, and dozen of 'internal' functions that should be
never called by the application (those reside in shema not visible by
the client application role - so the app developers can't easily get to
them).

> 
> I just re-read your original posting. You want to make thread B wait
> until thread A has committed. This will not be possible with the ACID
> levels. Even when using "serializable" for both threads. If thread B
> issues SELECT after thread A committed, then all works fine. If thread B
> issues SELECT before thread A commits, it sees the database in the state
> it was before thread A started its transaction (so even create_message
> has not been called). It cannot know whether thread A will COMMIT or
> ROLLBACK.

Well, what happens now is that thread A calls set_message_status, and
sets the status for the message to, let's say, 20. Then the thread
continues to work, and if everything goes well, does COMMIT at the end.
But, sometimes, if the calculations after the set_message_status take
longer (actually if the SMS gateway goes bezerk, the reconnection
timeout causes thread A to execute a bit longer) thread B starts doing
something for that message, and it needs to set the message status to
90. So it calls set_message_status, and commits. But, when thread A
commits, the status is back to 20. So I tought I'd do a rowlock while
doing an UPDATE on table messages (that's what set_message_status does)
so that thread B needs to wait untill thread A commits or rollbacks. If
it commits, thread B woud do the update, if it rollback, thread B would
return '0 rows updated' (because if thread A issues rollback at the end,
the create_message is also rolled back, so there is nothing to update
for thread B.). I tought serialization woud help here.

Part of my problem goes from working with MSSQL for too long :) There
you can have nested transactions, and you can have different isolation
levels for them.

But, apparently, there was an error in process design. Thread B is fired
up from within the calculations in thread A. But, thread B should be
started only and only if thread A commits. 

> 
> Transaction isolation is about consistency guarantees, not for true
> serialization. The reason for this is that databases with high load will
> need to allow paralellism.
> 
> So for your case, threas A should issue "NOTIFY" before COMMIT, and then
> thread B should use LISTEN and then wait for the notification before
> beginning its transaction. Be shure to read the paragraph about how
> "NOTIFY interacts with SQL transactions" in the NOTIFY documentation.

I've been playing with that, but performance drops significantly with
those notifications. And, it would be a hack. We redesigned the process
so it makes sense :)

> 
> I don't know the exact sematics of set_message_status and your checks,
> but it may be another solution to split thread A into two transactions
> by committing after step 3, and another BEGIN after step 4.

Yes, that was a guideline :) Thank you for your effort!
Mario
-- 
Mario Splivalo
Mob-Art
mario.splivalo@mobart.hr

"I can do it quick, I can do it cheap, I can do it well. Pick any two."




pgsql-sql by date:

Previous
From: andrew
Date:
Subject: Re: filtering after join
Next
From: frank church
Date:
Subject: REPOST:Memory Allocation error using pg_dump on 7.4