Thread: Are long term never commited SELECT statements are a problem?

Are long term never commited SELECT statements are a problem?

From
Erik Wasser
Date:
Hello List,

I've written an application in perl using DBI with MySQL (no transaction 
support). Then we decide to migrate it to postgresql 
(postgresql-8.0.1-r4).

At first we were using 'AutoCommit => 1' with the application. That 
means that every statement will be commited right away.

Then I discovered the 'magic of transactions' and set AutoCommit to 0. 
Then I rewrite many UPDATE and INSERT statements with support for 
commit and rollback. BUT: the SELECT statements were untouched (and 
that was mistake I think).

Now I've got here a blocking problem. Severel SQL statements (like 
renaming a field or UPDATE of a field) are blocked until I kill a 
certain task. This task DOES only the INSERTS and UPDATES with a 
transaction and the SELECT statements are not within an transaction. 
And this task is a long term running task (some kind of daemon) so the 
SELECT transactions will never be commited. Are long term never 
commited SELECT statements are a problem and could that lead to 
blocking other queries? 

To put it in annother way: what kind of thing I produced with the 
following pseudocode?

# open database
$DBH = DBI->connect(...,USERNAME,PASSWORD, { RaiseError => 1, AutoCommit 
=> 0 });

while (true)
{  # do some select  SELECT ... FROM ...  # do some more   SELECT ... FROM ...
  if (condition)     # do an UPDATE/INSERT     eval {        UPDATE/INSERT/...        $DBH->commit;     };     if ($@)
{       warn "Transaction aborted: $@";        eval { $DBH->rollback };     }  }
 
}

Is this some kind of nested transaction? Can there be a problem with 
this code?

Thanks for your help!

-- 
So long... Fuzz


Re: Are long term never commited SELECT statements are a

From
Achilleus Mantzios
Date:
O Erik Wasser έγραψε στις Jul 21, 2005 :

> Hello List,
> 
> I've written an application in perl using DBI with MySQL (no transaction 
> support). Then we decide to migrate it to postgresql 
> (postgresql-8.0.1-r4).
> 
> At first we were using 'AutoCommit => 1' with the application. That 
> means that every statement will be commited right away.
> 
> Then I discovered the 'magic of transactions' and set AutoCommit to 0. 
> Then I rewrite many UPDATE and INSERT statements with support for 
> commit and rollback. BUT: the SELECT statements were untouched (and 
> that was mistake I think).
> 
> Now I've got here a blocking problem. Severel SQL statements (like 
> renaming a field or UPDATE of a field) are blocked until I kill a 
> certain task. This task DOES only the INSERTS and UPDATES with a 
> transaction and the SELECT statements are not within an transaction. 
> And this task is a long term running task (some kind of daemon) so the 
> SELECT transactions will never be commited. Are long term never 
> commited SELECT statements are a problem and could that lead to 
> blocking other queries? 
> 
> To put it in annother way: what kind of thing I produced with the 
> following pseudocode?
> 
> # open database
> $DBH = DBI->connect(...,USERNAME,PASSWORD, { RaiseError => 1, AutoCommit 
> => 0 });
> 
> while (true)
> {
>    # do some select
>    SELECT ... FROM ...
>    # do some more 
>    SELECT ... FROM ...
> 
>    if (condition)
>       # do an UPDATE/INSERT
>       eval {
>          UPDATE/INSERT/...
>          $DBH->commit;
>       };
>       if ($@) {
>          warn "Transaction aborted: $@";
>          eval { $DBH->rollback };
>       }
>    }
> }
> 
> Is this some kind of nested transaction? Can there be a problem with 
> this code?

You mean savepoints?
In 8.x there is the feature of nested xactions.
But apparrently in your script you dont use them.

In general when working with BEGIN/COMMIT/ROLLBACK blocks
always be sure that you either rollback or commit
your transaction.
The need for this is more visible when using connection pools.
I am not familiar with the DBI semantics, but 
in your case it would be quite possible for
some job to block if another job's xaction has
already managed to update a row which the 1st job's xaction
tries to update too.

In any case, pure selects dont need to be in a xaction
unless you want to lock these rows, in which case
you use "FOR UPDATE".

In general you must dig a little deeper into PostgreSQL's
xaction mechanisms and policies,
since migrating from mysql requires some effort
regarding all new (to you) postgresql features.
The documentation (in the usual url) is superb.

> 
> Thanks for your help!
> 
> 

-- 
-Achilleus




Re: Are long term never commited SELECT statements are a problem?

From
Michael Fuhr
Date:
On Thu, Jul 21, 2005 at 03:57:56PM +0200, Erik Wasser wrote:
> Now I've got here a blocking problem. Severel SQL statements (like 
> renaming a field or UPDATE of a field) are blocked until I kill a 
> certain task. This task DOES only the INSERTS and UPDATES with a 
> transaction and the SELECT statements are not within an transaction. 

If you set AutoCommit to 0 then all statements are inside a
transaction.  As you've discovered, SELECT acquires certain locks
that persist for the duration of the transaction, so you must commit
or roll back the transaction to release those locks (read up on
transaction theory to learn more about the rationale for this).

-- 
Michael Fuhr
http://www.fuhr.org/~mfuhr/


Re: Are long term never commited SELECT statements are a problem?

From
Erik Wasser
Date:
On Thursday 21 July 2005 17:18, Michael Fuhr wrote:

> If you set AutoCommit to 0 then all statements are inside a
> transaction.  As you've discovered, SELECT acquires certain locks
> that persist for the duration of the transaction, so you must commit
> or roll back the transaction to release those locks (read up on
> transaction theory to learn more about the rationale for this).

What URL should I read at first? I began with 
'http://www.postgresql.org/docs/8.0/interactive/transaction-iso.html'. 
Is this the right page for starters?

BTW: I quote from the page:

> When a transaction is on the serializable level, a SELECT query sees
> only data committed before the transaction began; it never sees either
> uncommitted data or changes committed during transaction execution by
> concurrent transactions. (However, the SELECT does see the effects of
> previous updates executed within its own transaction, even though they
> are not yet committed.)     

So I opened up two shells and started 'psql' on both shells (marked the 
command with 1 and 2):

1:begin

2:begin;

1:SELECT * FROM test;id | name
----+------
(0 rows)

2: INSERT INTO test (name) VALUES ('foo');

1: SELECT * FROM test;id | name
----+------
(0 rows)

2: commit;

1: SELECT * FROM test;id | name
----+------ 1 | foo
(1 row)

Why do I see in the first transaction data from the commited second 
transaction? Doesn't prove that the documentation on the above URL 
wrong?

-- 
So long... Fuzz


Re: Are long term never commited SELECT statements are a problem?

From
Alvaro Herrera
Date:
On Thu, Jul 21, 2005 at 05:40:57PM +0200, Erik Wasser wrote:

> > When a transaction is on the serializable level, a SELECT query sees
> > only data committed before the transaction began; it never sees either
> > uncommitted data or changes committed during transaction execution by
> > concurrent transactions. (However, the SELECT does see the effects of
> > previous updates executed within its own transaction, even though they
> > are not yet committed.)     

> Why do I see in the first transaction data from the commited second 
> transaction? Doesn't prove that the documentation on the above URL 
> wrong?

Because it says "in the serializable level," which they acquire when you
execute "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE".

-- 
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
Officer Krupke, what are we to do?
Gee, officer Krupke, Krup you! (West Side Story, "Gee, Officer Krupke")


Re: Are long term never commited SELECT statements are a problem?

From
Michael Fuhr
Date:
On Thu, Jul 21, 2005 at 05:40:57PM +0200, Erik Wasser wrote:
> Why do I see in the first transaction data from the commited second 
> transaction? Doesn't prove that the documentation on the above URL 
> wrong?

No, it doesn't.  The quote you posted refers to the SERIALIZABLE
isolation level, but the default is READ COMMITTED.  Unless you've
changed the default (and it appears that you haven't), then
transactions that don't set an isolation level will default to READ
COMMITTED.

The following command shows what isolation level the current
transaction is using:

SHOW transaction_isolation;

Try your example again, but issue the following command in transaction 1
before doing anything else:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- 
Michael Fuhr
http://www.fuhr.org/~mfuhr/