Обсуждение: autocommit and stored procedures

Поиск
Список
Период
Сортировка

autocommit and stored procedures

От
roehm@it.usyd.edu.au
Дата:
Hi,

Which command granularity does the JDBC driver's autocommit have?
Does it commit after each client-side JDBC statement, or does it commit
each individual SQL statement on the server-side?
In particular, does an JDBC autocommit around the call to a stored
procedure
commit each statement within that stored procedure, or does it commit
the
procedure as a whole?

Example:

Stored Procedure
----------------
CREATE PROCEDURE Test (n varying character,val REAL)
DECLARE
    cid INTEGER;
BEGIN
    SELECT custid INTO cid
      FROM account
     WHERE name=n;

    UPDATE checking
       SET balance=balance-val
     WHERE custid=cid;
END;

JDBC Code
---------
Connection conn;
CallableStatement cstmt;
conn.setAutoCommit(true);
cstmt = conn.prepareCall("{call Test(?,?)}");
cstmt.setString(1, name);
cstmt.setString(2, value);
cstmt.execute();


Does PostgreSQL execute one commit after the execution of Test(),
i.e. do select and update run in one transaction?
Or will PostgreSQL commit after the select and then again after the
update
inside the Test() procedure?

Does anyone know what the specified behaviour is for JDBC AutoCommit?

Many thanks

Uwe



Re: autocommit and stored procedures

От
Mark Lewis
Дата:
On Wed, 2007-08-15 at 21:21 +1000, roehm@it.usyd.edu.au wrote:
> Hi,
>
> Which command granularity does the JDBC driver's autocommit have?
> Does it commit after each client-side JDBC statement, or does it commit
> each individual SQL statement on the server-side?
> In particular, does an JDBC autocommit around the call to a stored
> procedure
> commit each statement within that stored procedure, or does it commit
> the
> procedure as a whole?
>
> Example:
>
> Stored Procedure
> ----------------
> CREATE PROCEDURE Test (n varying character,val REAL)
> DECLARE
>     cid INTEGER;
> BEGIN
>     SELECT custid INTO cid
>       FROM account
>      WHERE name=n;
>
>     UPDATE checking
>        SET balance=balance-val
>      WHERE custid=cid;
> END;
>
> JDBC Code
> ---------
> Connection conn;
> CallableStatement cstmt;
> conn.setAutoCommit(true);
> cstmt = conn.prepareCall("{call Test(?,?)}");
> cstmt.setString(1, name);
> cstmt.setString(2, value);
> cstmt.execute();
>
>
> Does PostgreSQL execute one commit after the execution of Test(),
> i.e. do select and update run in one transaction?
> Or will PostgreSQL commit after the select and then again after the
> update
> inside the Test() procedure?
>
> Does anyone know what the specified behaviour is for JDBC AutoCommit?
>
> Many thanks
>
> Uwe


The JDBC driver manages the autocommit flag by not beginning a new
transaction at all, since in PostgreSQL all statements execute in their
own private transactions unless an explicit transaction is started with
the BEGIN statement.

Therefore, you would expect each individual statement (as recognized by
the PG back-end, not by your Java code) to execute and commit
individually.

I do not know whether or not JDBC specifies a behavior for this case,
but given the intentional vagueness of the spec in several areas, I
would be very surprised if the the spec weren't either silent or
answered, "Executing multiple SQL commands in a single JDBC command is
unsupported and may result in unspecified, driver-specific behavior".

-- Mark

Re: autocommit and stored procedures

От
Oliver Jowett
Дата:
roehm@it.usyd.edu.au wrote:

> Which command granularity does the JDBC driver's autocommit have?
> Does it commit after each client-side JDBC statement, or does it commit
> each individual SQL statement on the server-side?

It effectively commits after each client-side JDBC statement execution,
even if you provide multiple semicolon-separated queries in a single
statement. At the protocol level the driver converts a single JDBC
statement into one or more groups of Parse/Bind/Execute messages,
followed by a single Sync. You can see this if you look at the debugging
produced with loglevel=2. Also see
http://www.postgresql.org/docs/8.2/static/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY

Regardless of that, there's no way I know of to get "autocommit" within
a stored procedure as you seem to be wanting, regardless of what client
driver you're using, because the server will always set up a transaction
(one way or another) before executing the top-level query that runs your
stored procedure so by the time your stored procedure is running it's
too late to think about transaction demarcation.

> Does anyone know what the specified behaviour is for JDBC AutoCommit?

See the javadoc for Connection.setAutoCommit():

> The commit occurs when the statement completes or the next execute occurs, whichever comes first. In the case of
statementsreturning a ResultSet object, the statement completes when the last row of the ResultSet object has been
retrievedor the ResultSet object has been closed. In advanced cases, a single statement may return multiple results as
wellas output parameter values. In these cases, the commit occurs when all results and output parameter values have
beenretrieved. 

-O


Re: autocommit and stored procedures

От
Mark Lewis
Дата:
On Thu, 2007-08-16 at 02:06 +1200, Oliver Jowett wrote:
> roehm@it.usyd.edu.au wrote:
>
> > Which command granularity does the JDBC driver's autocommit have?
> > Does it commit after each client-side JDBC statement, or does it commit
> > each individual SQL statement on the server-side?
>
> It effectively commits after each client-side JDBC statement execution,
> even if you provide multiple semicolon-separated queries in a single
> statement. At the protocol level the driver converts a single JDBC
> statement into one or more groups of Parse/Bind/Execute messages,
> followed by a single Sync. You can see this if you look at the debugging
> produced with loglevel=2. Also see
> http://www.postgresql.org/docs/8.2/static/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY

Did this change with v3 protocol?  I'm not positive, but I remember
thinking that it used to commit each statement individually quite a
while back, but that would have been in the days of the v2 protocol.

If that's the case, then maybe using v2 protocol would suffice for
executing multiple statements at a time with a single auto-commit?

But yeah, none of this really seems to apply to the original poster's
question anyway.

-- Mark Lewis

Re: autocommit and stored procedures

От
roehm@it.usyd.edu.au
Дата:
Thanks for the prompt answer.
I had a look into the source code in the meanwhile and it seems as
you say:
Autocommit(true) means no explicit BEGIN transaction from the JDBC
driver,
which at the server side means an implicit transaction around the
command sent.
If that is a stored procedure call, the whole stored procedure runs
as one transaction.

Uwe


On 15 Aug 2007, at 23:50, Mark Lewis wrote:

> On Wed, 2007-08-15 at 21:21 +1000, roehm@it.usyd.edu.au wrote:
>> Hi,
>>
>> Which command granularity does the JDBC driver's autocommit have?
>> Does it commit after each client-side JDBC statement, or does it
>> commit
>> each individual SQL statement on the server-side?
>> In particular, does an JDBC autocommit around the call to a stored
>> procedure
>> commit each statement within that stored procedure, or does it commit
>> the
>> procedure as a whole?
>>
>> Example:
>>
>> Stored Procedure
>> ----------------
>> CREATE PROCEDURE Test (n varying character,val REAL)
>> DECLARE
>>     cid INTEGER;
>> BEGIN
>>     SELECT custid INTO cid
>>       FROM account
>>      WHERE name=n;
>>
>>     UPDATE checking
>>        SET balance=balance-val
>>      WHERE custid=cid;
>> END;
>>
>> JDBC Code
>> ---------
>> Connection conn;
>> CallableStatement cstmt;
>> conn.setAutoCommit(true);
>> cstmt = conn.prepareCall("{call Test(?,?)}");
>> cstmt.setString(1, name);
>> cstmt.setString(2, value);
>> cstmt.execute();
>>
>>
>> Does PostgreSQL execute one commit after the execution of Test(),
>> i.e. do select and update run in one transaction?
>> Or will PostgreSQL commit after the select and then again after the
>> update
>> inside the Test() procedure?
>>
>> Does anyone know what the specified behaviour is for JDBC AutoCommit?
>>
>> Many thanks
>>
>> Uwe
>
>
> The JDBC driver manages the autocommit flag by not beginning a new
> transaction at all, since in PostgreSQL all statements execute in
> their
> own private transactions unless an explicit transaction is started
> with
> the BEGIN statement.
>
> Therefore, you would expect each individual statement (as
> recognized by
> the PG back-end, not by your Java code) to execute and commit
> individually.
>
> I do not know whether or not JDBC specifies a behavior for this case,
> but given the intentional vagueness of the spec in several areas, I
> would be very surprised if the the spec weren't either silent or
> answered, "Executing multiple SQL commands in a single JDBC command is
> unsupported and may result in unspecified, driver-specific behavior".
>
> -- Mark
>

--
Dr. Uwe Roehm
School of Information Technologies
University of Sydney, NSW 2006, Australia




Re: autocommit and stored procedures

От
roehm@it.usyd.edu.au
Дата:
On 16 Aug 2007, at 0:06, Oliver Jowett wrote:

> roehm@it.usyd.edu.au wrote:
>
>> Which command granularity does the JDBC driver's autocommit have?
>> Does it commit after each client-side JDBC statement, or does it
>> commit
>> each individual SQL statement on the server-side?
>
> It effectively commits after each client-side JDBC statement
> execution, even if you provide multiple semicolon-separated queries
> in a single statement. At the protocol level the driver converts a
> single JDBC statement into one or more groups of Parse/Bind/Execute
> messages, followed by a single Sync. You can see this if you look
> at the debugging produced with loglevel=2. Also see http://
> www.postgresql.org/docs/8.2/static/protocol-flow.html#PROTOCOL-FLOW-
> EXT-QUERY
>
Ah - I wasn't aware of that debug mode. Thanks!

> Regardless of that, there's no way I know of to get "autocommit"
> within a stored procedure as you seem to be wanting, regardless of
> what client driver you're using, because the server will always set
> up a transaction (one way or another) before executing the top-
> level query that runs your stored procedure so by the time your
> stored procedure is running it's too late to think about
> transaction demarcation.
>
I did not say anything about 'what I want' ;-)
As a matter of fact, postgres' behaviour is what we wanted and
expected, i.e. the
call to execute a stored procedure gets committed, meaning that all
the statements
within are running within the same transaction context.

I came up with this question when we were doing some tests regarding
snapshot isolation
on different database engines, but with some unexpected results from
the very same client code.
Apparantly SQL Server does a 'transitive' autocommit which promotes
inside stored procedures,
committing each individual statement within!

>> Does anyone know what the specified behaviour is for JDBC AutoCommit?
>
> See the javadoc for Connection.setAutoCommit():
>
That's your documentation and not necessarily the JDBC specification ;-)
I wonder whether this is a hole in that spec or a bug...
Cf. also this part of Sybase's SQL Anywhere documentation:
   http://www.ianywhere.com/developer/product_manuals/sqlanywhere/
1000/en/html/dbpgen10/pg-autocommit-implementation-sqlapp.html
According to this, the autocommit is controlled at the server side
(for Sybase Anywhere SQL).
Now which definition of the behaviour is correct?

Again: Our test client and the transactions coded as stored
procedures behave different
        depending on whether we use postgres or SQL Server as backend...
        (if we set Autocommit(true))

>> The commit occurs when the statement comp
>> letes or the next execute occurs, whichever comes first. In the
>> case of statements returning a ResultSet object, the statement
>> completes when the last row of the ResultSet object has been
>> retrieved or the ResultSet object has been closed. In advanced
>> cases, a single statement may return multiple results as well as
>> output parameter values. In these cases, the commit occurs when
>> all results and output parameter values have been retrieved.
>
> -O
Great - thanks.

Uwe



Re: autocommit and stored procedures

От
Oliver Jowett
Дата:
roehm@it.usyd.edu.au wrote:

>> See the javadoc for Connection.setAutoCommit():
>>
> That's your documentation and not necessarily the JDBC specification ;-)

Err I am talking about:

http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Connection.html#getAutoCommit()

which certainly is part of the JDBC specification.

-O

Re: autocommit and stored procedures

От
roehm@it.usyd.edu.au
Дата:
On 16 Aug 2007, at 17:44, Oliver Jowett wrote:

> roehm@it.usyd.edu.au wrote:
>
>>> See the javadoc for Connection.setAutoCommit():
>>>
>> That's your documentation and not necessarily the JDBC
>> specification ;-)
>
> Err I am talking about:
>
> http://java.sun.com/j2se/1.5.0/docs/api/java/sql/
> Connection.html#setAutoCommit()
>
> which certainly is part of the JDBC specification.
>
> -O

Thanks, that's better - the documentation of Sun's reference
implementation.

Btw: The actual JDBC specification can be downlaoded from here:
http://java.sun.com/products/jdbc/download.html#corespec30

In Chapter 10.1, it seems to define the autocommit behaviour as
discussed so far
(commit outside the stored procedure after all of its results have
been received).

Uwe

Re: autocommit and stored procedures

От
"Albe Laurenz"
Дата:
roehm@it.usyd.edu.au wrote:
> In particular, does an JDBC autocommit around the call to a stored
> procedure commit each statement within that stored procedure, or does
> it commit the procedure as a whole?

A function in PostgreSQL is always executed within one single
transaction, so you cannot commit only part of the SQL-statements
within a function.

The JDBC 4.0 specification says:

 The Connection attribute auto-commit specifies when to end transactions. Enabling
 auto-commit causes a transaction commit after each individual SQL statement as
 soon as that statement is complete. The point at which a statement is considered to
 be "complete" depends on the type of SQL statement as well as what the application
 does after executing it:

 ■ For Data Manipulation Language (DML) statements such as Insert, Update,
 Delete, and DDL statements, the statement is complete as soon as it has finished
 executing.
 ■ For Select statements, the statement is complete when the associated result set
 is closed.
 ■ For CallableStatement objects or for statements that return multiple results,
 the statement is complete when all of the associated result sets have been closed,
 and all update counts and output parameters have been retrieved.

To me that seems to mean that if I do

executeUpdate("SELECT myfunction()")

the autocommit should occur after the select statement is finished, i.e.
after the complete function has been executed.

But I'll admit that this is disputable...

Yours,
Laurenz Albe

Re: autocommit and stored procedures

От
Dave Cramer
Дата:
On 16-Aug-07, at 5:46 AM, Albe Laurenz wrote:

> roehm@it.usyd.edu.au wrote:
>> In particular, does an JDBC autocommit around the call to a stored
>> procedure commit each statement within that stored procedure, or does
>> it commit the procedure as a whole?
>
> A function in PostgreSQL is always executed within one single
> transaction, so you cannot commit only part of the SQL-statements
> within a function.
>
> The JDBC 4.0 specification says:
>
>  The Connection attribute auto-commit specifies when to end
> transactions. Enabling
>  auto-commit causes a transaction commit after each individual SQL
> statement as
>  soon as that statement is complete. The point at which a statement
> is considered to
>  be "complete" depends on the type of SQL statement as well as what
> the application
>  does after executing it:
>
>  ■ For Data Manipulation Language (DML) statements such as Insert,
> Update,
>  Delete, and DDL statements, the statement is complete as soon as
> it has finished
>  executing.
>  ■ For Select statements, the statement is complete when the
> associated result set
>  is closed.
>  ■ For CallableStatement objects or for statements that return
> multiple results,
>  the statement is complete when all of the associated result sets
> have been closed,
>  and all update counts and output parameters have been retrieved.


Isn't that interesting I wonder who's database has the above select
and CallableStatement semantics.

Dave
>
> To me that seems to mean that if I do
>
> executeUpdate("SELECT myfunction()")
>
> the autocommit should occur after the select statement is finished,
> i.e.
> after the complete function has been executed.
>
> But I'll admit that this is disputable...
>
> Yours,
> Laurenz Albe
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match