Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
DB Engine
SQL ServerMSDESQL Server CE
Services
Analysis (Data Mining)Analysis (OLAP)DTSIntegration ServicesNotification ServicesReporting Services
Programming
CLRConnectivitySQLXML
Other Technologies
ClusteringEnglish QueryFull-Text SearchReplicationService Broker
General
Data WarehousingPerformanceSecuritySetupSQL Server ToolsOther SQL Server Topics
DirectoryUser Groups
Related Topics
MS AccessOther DB ProductsMS Server Products.NET DevelopmentVB DevelopmentJava DevelopmentMore Topics ...

SQL Server Forum / Programming / Connectivity / January 2006

Tip: Looking for answers? Try searching our database.

Behavior of Connection.commit()

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Wes Clark - 20 Jan 2006 17:32 GMT
Running with "SET IMPLICIT_TRANSACTIONS ON", with the old driver we would
sometimes issue a commit on a connection when no work had been done on the
connection, and we would never get "Msg 3902, Level 16, State 1, Line 1
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."  We
are now getting this message.  Did the old driver know no statements had been
issued on the connection since the last commit, and not issue the command to
the server?  We use a framework do manage the database interface.
Wes Clark - 20 Jan 2006 18:03 GMT
Actually, we call setAutoCommit(false) on the connection, we don't issue "SET
IMPLICIT_TRANSACTIONS ON" via sql.
Joe Weinstein - 20 Jan 2006 18:16 GMT
> Actually, we call setAutoCommit(false) on the connection, we don't issue "SET
> IMPLICIT_TRANSACTIONS ON" via sql.

Whew, good. I'm sure you know how bad form it would be to mix transactional
control between JDBC and DBMS-specific SQL. (I've seen it done!). Can you
verify that you *always* call setAutoCommit(false) before calling commit()?
thanks,
Joe Weinstein at BEA Systems
Jerry Brenner - 20 Jan 2006 18:25 GMT
Joe, funny meeting you here.

We call setAutoCommit(false) when we first get a connection, just prior to
putting it into the connection pool.  If we need to change it for some
reason, then we always change it back before committing.

> > Actually, we call setAutoCommit(false) on the connection, we don't issue "SET
> > IMPLICIT_TRANSACTIONS ON" via sql.
[quoted text clipped - 4 lines]
> thanks,
> Joe Weinstein at BEA Systems
Joe Weinstein - 20 Jan 2006 18:42 GMT
> Joe, funny meeting you here.
>
> We call setAutoCommit(false) when we first get a connection, just prior to
> putting it into the connection pool.  If we need to change it for some
> reason, then we always change it back before committing.

Hi Jerry! Good to hear from you, and MS will benefit greatly by
working with you on driver/DBMS query plan issues... I am unable
to duplicate the problem with the commit() call with some cheap JDBC
I tried... If you can provide a repro or trace the execution history
of a connection that throws this exception, that would be cool.

Email me
j
o
e
AT
b
e
a
DOT
c
o
m

>>>Actually, we call setAutoCommit(false) on the connection, we don't issue "SET
>>>IMPLICIT_TRANSACTIONS ON" via sql.
[quoted text clipped - 4 lines]
>>thanks,
>>Joe Weinstein at BEA Systems
Angel Saenz-Badillos[MS] - 20 Jan 2006 19:45 GMT
"The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."

This could be a very serious error. This may not be what is affecting your
scenario but here is some information that may be applicable. The basic
problem is that high severity SQL exceptions (level 16 or higher) can
rollback the transaction on the server. When this happens the old driver was
masking the error during COMMIT with something like the following TSQL:

IF @@TRANCOUNT > 0 COMMIT TRAN  //If there is a transaction active commit
it, otherwise do nothing.

We decided that faking a transaction commit was a bad idea and in the new
driver replaced it with something like:
COMMIT TRAN //Commit transaction, if no transaction active throw exception.

What this means is that the following scenario would behave

//start transaction
//insert data 1
//execute something that throws lev 16 server exception and ignore
exception. At this time insert data 1 has been rolled back!
//insert data 2
//COMMIT

In the old driver in this scenario commit would silently "work" (not throw
an exception), even though insert data 1 has been rolled back. In the new
driver this will now throw an exception and you will at least know that not
all is well. We felt that it was an important breaking change to make.

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

>> Joe, funny meeting you here.
>>
[quoted text clipped - 31 lines]
>>>thanks,
>>>Joe Weinstein at BEA Systems
Joe Weinstein - 20 Jan 2006 20:18 GMT
> "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."
>
[quoted text clipped - 24 lines]
> driver this will now throw an exception and you will at least know that not
> all is well. We felt that it was an important breaking change to make.

Interesting... So what does the driver do with:

c = d.connect(URL, props);
c.setAutoCommit(false); // does *not start a tx*
s.commit();

Also, when the driver throws the exception above, in
a circumstance you suggest, presumably the connection
is still in autoCommit(false) mode. Is it?

Joe Weinstein at BEA Systems.
Angel Saenz-Badillos[MS] - 20 Jan 2006 22:48 GMT
You have to remember that Sql Server does not understand the concept of a
autoCommit(false) state, we have to fake this with "Begin transaction"
blocks. By default the Sql Server database is in the equivalent of
autoCommit(true) state, anything you do  will permanently update the
database.

When we set autoCommit to off the expectation is that no SQL statements will
be committed (that is, the database will not be permanently updated) until
you have explicitly told it to commit by invoking the commit() method. To do
this in Sql Server we issue the following command to the server:

> c = d.connect(URL, props);
> c.setAutoCommit(false);
IF @@TRANCOUNT = 0 BEGIN TRAN //if we are currently not in a transaction,
start one.
> s.commit();
COMMIT TRAN; IF @@TRANCOUNT = 0 BEGIN TRAN  //Commit the existing
transaction, start a new transaction to fake the fact that we are still in
autoCommit(false) state.

> Also, when the driver throws the exception above, in
> a circumstance you suggest, presumably the connection
> is still in autoCommit(false) mode. Is it?

Thanks to the BEGIN TRAN at the end of the commit it would be, but this
should be no consolation. When you receive the "no corresponding begin"
exception you probably have data corruption.

We recently  looked into this error for a large customer. They started
getting this error with our driver and filed it as a bug. When we
investigated it turned out that they were doing something as inoquous as

try{
//create table
}catch{
//ignore failure, this means that table already existed. }

This was sometimes running inside of a transaction, when the table was
already in the database the Sql Exception would roll back the transaction
but they would ignore it. With their previous driver they had no idea that
everything before the above code was being rolled back.

I really should put this in an easier to read format, maybe a blog with
source code you can try.

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

>> "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."
>>
[quoted text clipped - 39 lines]
>
> Joe Weinstein at BEA Systems.
Joe Weinstein - 20 Jan 2006 23:20 GMT
> You have to remember that Sql Server does not understand the concept of a
> autoCommit(false) state, we have to fake this with "Begin transaction"
[quoted text clipped - 12 lines]
> IF @@TRANCOUNT = 0 BEGIN TRAN //if we are currently not in a transaction,
> start one.

Surely the driver can do "set implicit_transactions on" instead of
that. My old driver from '96 does this:

setAutoCommit(true):  "if (@@trancount > 0) rollback transaction set implicit_transactions off"
setAutoCommit(false): "if (@@trancount > 0) rollback transaction set implicit_transactions on"

Joe Weinstein at BEA Systems

>>s.commit();
>
[quoted text clipped - 26 lines]
> I really should put this in an easier to read format, maybe a blog with
> source code you can try.
Angel Saenz-Badillos[MS] - 20 Jan 2006 23:25 GMT
Just a quick repro program that explains the problem, I would be interested
to see how other Sql Server drivers handle this:

import java.lang.*;
import java.util.*;
import java.sql.*;
import java.math.*;
import java.text.*;
import java.io.*;

public class test
{
public static String ConnectionString = "<set your connection string
here>";

public static void main(String[] args) throws Exception
{
 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
 Connection conn = DriverManager.getConnection(ConnectionString);
 Statement stmt = conn.createStatement();
 String tablename= "testTX";
 stmt.executeUpdate("if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[" + tablename + "]') and OBJECTPROPERTY(id,
N'IsUserTable') = 1) DROP TABLE [" + tablename + "]");
 stmt.executeUpdate("CREATE TABLE [" + tablename + "] (a int)");

 conn.setAutoCommit(false);
 stmt.executeUpdate("INSERT into [" + tablename+ "] values (1)");
 try{
  //This will kill the transaction!
  stmt.executeUpdate("CREATE TABLE [" + tablename + "] (a int)");
 }catch(Exception ex){System.out.println(ex.getMessage());}
 stmt.executeUpdate("INSERT into [" + tablename+ "] values (99999)");
 try{
  conn.commit();
 }catch(Exception ex){System.out.println("We correctly throw an exception:
"+ex.getMessage());}
 conn.close();

 //Verify data inserted.
 Connection conn2 = DriverManager.getConnection(ConnectionString);
 Statement stmt2 = conn2.createStatement();
 ResultSet rs = stmt2.executeQuery("SELECT * FROM [" + tablename + "]");
 while(rs.next()){
  System.out.println(rs.getObject(1));
 }
 System.out.println("If this did not print out 2 lines: 1, 99999 you have
data corruption.");
}
}

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

>> You have to remember that Sql Server does not understand the concept of a
>> autoCommit(false) state, we have to fake this with "Begin transaction"
[quoted text clipped - 54 lines]
>> I really should put this in an easier to read format, maybe a blog with
>> source code you can try.
Joe Weinstein - 20 Jan 2006 23:51 GMT
Ok, I just tested another driver that fails the tx because
the table is there. The subsequent commit does not fail.
The select gives only the 9999 row. I don't understand
how your program expects the commit to fail, but
then expects the row inserted in a failed tx to still
be there?
Joe

> Just a quick repro program that explains the problem, I would be interested
> to see how other Sql Server drivers handle this:
[quoted text clipped - 46 lines]
>  }
> }
Angel Saenz-Badillos[MS] - 21 Jan 2006 00:04 GMT
Thank you for taking the time to test this with another driver. The
intention of the program is to show that with this driver when you get this
type of data corruption we will throw on Commit. It is an ugly problem, but
to us it seemed like a better option than having commit succeed and silently
corrupting your data.

This is why I mentioned that this could be a very serious error, your code
could be silently corrupting your data with your previous driver. With this
driver you can at least realize that there may be a problem but it will
probably require code changes to fix the underlying issue.

>I don't understand
> how your program expects the commit to fail, but
> then expects the row inserted in a failed tx to still
> be there?
I am sorry for not making it clearer, I am afraid I just threw it together
to post it while everybody is looking at this thread. The program was
intended to show that others drivers that don't throw on commit still have
the same data corruption issue.

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

> Ok, I just tested another driver that fails the tx because
> the table is there. The subsequent commit does not fail.
[quoted text clipped - 54 lines]
>>  }
>> }
Joe Weinstein - 21 Jan 2006 00:58 GMT
> Thank you for taking the time to test this with another driver. The
> intention of the program is to show that with this driver when you get this
[quoted text clipped - 6 lines]
> driver you can at least realize that there may be a problem but it will
> probably require code changes to fix the underlying issue.

Understood. It is in fact the DBMS that throws us all most of the
curve balls. The DBMS should treat every SQL failure the same. If
somewhere in a tx we try to insert a value into a row where it doesn't
fit, we get an exception, but the tx is still alive for us to pursue
or close as we see fit. In the rare case where someone tries DDL in a
transaction, it shouldn't logically be any different.
   I I alter the program so the failure is updating a varchar(1)
to be '333', it also throws an exception, but afterwards I am able to
commit or rollback as I choose.
    So, the driver author's problem is what to do... I would code to
at least support the mode where any unexepected SQLException is
reacted to by a rollback(). However, I agree that for those
'executive decisions' the DBMS will make, to roll back your
exception immediately, the driver should make any immediate
commit() fail, and have it say "Commit failed because current
tx was chosen as a deadlock victim", or Commit failed because
DDL-in-tran failed". This info would have to be cached by the
driver from the exception during the execute call, and then
serve it up on commit... (Joe say thinking thinly while typing...)
Joe

>>I don't understand
>>how your program expects the commit to fail, but
[quoted text clipped - 5 lines]
> intended to show that others drivers that don't throw on commit still have
> the same data corruption issue.
Sam Wilson - 21 Jan 2006 01:59 GMT
I'm with Joe... I'm a bit concerned why the driver doesn't issue "set
implicit_transactions on" which is the logical equivalent of
setAutoCommit(false).

Am I missing something or is this functionality not analogous??

Thanks,

Sam Wilson
Ecount, Inc.

> > You have to remember that Sql Server does not understand the concept of a
> > autoCommit(false) state, we have to fake this with "Begin transaction"
[quoted text clipped - 51 lines]
> > I really should put this in an easier to read format, maybe a blog with
> > source code you can try.
Angel Saenz-Badillos[MS] - 23 Jan 2006 19:11 GMT
Sam,
The problem is the same as above. If we set set_implicit_transactions on we
will no longer be able to tell that a serious issue happened on commit and
we would not throw an exception:

//start transaction
//insert data 1
//execute ddl
exception. At this time insert data 1 has been rolled back!
//insert data 2 //with set_implicit_transactions on this will create a NEW
transaction under the covers.
//COMMIT will no longer throw an exception, it will commit the transaction
started with insert data 2 and you will silently ignore the fact that data 1
has been rolled back.

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

> I'm with Joe... I'm a bit concerned why the driver doesn't issue "set
> implicit_transactions on" which is the logical equivalent of
[quoted text clipped - 73 lines]
>> > I really should put this in an easier to read format, maybe a blog with
>> > source code you can try.
Joe Weinstein - 23 Jan 2006 19:48 GMT
> Sam,
> The problem is the same as above. If we set set_implicit_transactions on we
[quoted text clipped - 7 lines]
> //insert data 2 //with set_implicit_transactions on this will create a NEW
> transaction under the covers.

Understood. One other thing to consider is if the driver can know from
the DBMS message when (the rare case such as deadlock or DDL) when the
DBMS has already killed the whole tx, and in that case, throw an exception
from any subsequent connection, statement or result set method that would/could
do an update or query (because it may hold locks) (from this connection)
saying "The DBMS has killed the current transaction. No further DBMS
access is allowed until you call rollback()".

> //COMMIT will no longer throw an exception, it will commit the transaction
> started with insert data 2 and you will silently ignore the fact that data 1
> has been rolled back.

Correct, but there is a problem as soon as the tx has been rolled back,
and there can be troubles even allowing the insert data 2 to proceed. The
user application may depend on holding locks in order, and once it is
allowed to proceed obtaining the lock for data 2, it may then go on to
obtain other locks before trying to commit, and this not-expected order
of locking (data 1 and any other data previously locked are now unlocked)
may cause deadlocks that could kill other innocent, correct transactions.
HTH,
Joe
Angel Saenz-Badillos[MS] - 23 Jan 2006 20:21 GMT
This is completely correct; throwing an exception on commit is only a band
aid and still causes too much pain.

>throw an exception from any subsequent connection, statement or result

>set >method that would/could do an update or query

This would be the only real solution to this problem. The big IF of course
is whether we can correctly determine all cases in which the transaction has
been rolled back by the DBMS...

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

>> Sam,
>> The problem is the same as above. If we set set_implicit_transactions on
[quoted text clipped - 30 lines]
> HTH,
> Joe
Wes Clark - 24 Jan 2006 22:59 GMT
It turns out in very limited circumstances in a few test programs, we were
sending a "commit" sql statement to the database.  A developer found this in
a trace we send in.  This was messing up the driver.  And I don't think this
is related to most of the discussion on this thread.

I would suggest that if the driver needs to keep track of the state of the
transaction, it would be advisable to look for SQL statements that would
affect that state.  I don’t think the JDBC spec would say you can’t commit a
transaction using the SQL.

I imagine the other drivers do that very thing.  Do you accept this as a
“bug” and/or should I enter this somewhere else?

Thank you for helping us get back on the road.
Joe Weinstein - 24 Jan 2006 23:29 GMT
> It turns out in very limited circumstances in a few test programs, we were
> sending a "commit" sql statement to the database.  A developer found this in
[quoted text clipped - 5 lines]
> affect that state.  I don’t think the JDBC spec would say you can’t commit a
> transaction using the SQL.

I'd take the other position. The load imposed by the driver having to parse all the SQL,
looking for commits, rollbacks etc in SQL would be onerous and inappropriate. It would
be clearly poor style to distribute control of transactions between JDBC and SQL.
Procedures could have 'commit' in them and the driver could never know.

> I imagine the other drivers do that very thing.  Do you accept this as a
> “bug” and/or should I enter this somewhere else?

They don't. I highly recommend controling your transactions within
a top-level method that does all the tx work and then calls
commit() or rollback, or letting a tx-capable container do it all for
you.
Joe Weinstein at BEA Systems

> Thank you for helping us get back on the road.
Wes Clark - 25 Jan 2006 00:37 GMT
I'm interested in Microsoft's response.  Does anyone know what the JDBC spec
says here?  Does it say "commit" and "rollback"  and other SQL commands that
affect the transaction state are not allowed?  If so, should the driver throw
an error?  That would also require parsing, of course.

How about in a batch of statements?   How sure can the driver ever be about
the state of the transaction?

> > It turns out in very limited circumstances in a few test programs, we were
> > sending a "commit" sql statement to the database.  A developer found this in
[quoted text clipped - 21 lines]
>
> > Thank you for helping us get back on the road.
Joe Weinstein - 25 Jan 2006 01:20 GMT
> I'm interested in Microsoft's response.  Does anyone know what the JDBC spec
> says here?  Does it say "commit" and "rollback"  and other SQL commands that
[quoted text clipped - 3 lines]
> How about in a batch of statements?   How sure can the driver ever be about
> the state of the transaction?

We will await MS's response. In the meantime, the spec says nothing. It also
doesn't say what happens if the JDBC driver sends "shutdown" SQL to the DBMS
either. A batch of statements doesn't add any more complexity. The driver must
assume the transactional status is as it was set the last time via JDBC. Drivers
will never parse SQL for transactional semantics, let alone presume to react
to them, and stored procedures or even triggers could easily subvert any such
effort.
I can promise you as a former JDBC spec member and co-author of the first
commercial JDBC drivers on the market for MS SQLServer, Sybase, Oracle, and
Informix, and as a DBMS guy (joe@sybase.com '88-'96) that you should always
define, control and terminate a tx with only one API and in one logical place.
Good luck, I want you to be successful.
Joe Weinstein at BEA Systems

>>>It turns out in very limited circumstances in a few test programs, we were
>>>sending a "commit" sql statement to the database.  A developer found this in
[quoted text clipped - 21 lines]
>>
>>>Thank you for helping us get back on the road.
Angel Saenz-Badillos[MS] - 25 Jan 2006 01:37 GMT
We will definitelly be looking at this and the separate issue with
exceptions, I am glad to hear that the inmediate issue at least is resolved.

I can't think of a single driver in existance today for Sql Server that
handles both TSQL and API transaction handling simultaneously, making this
scenario work is going to be very tough. One thing we _could_ do would be to
throw an exception whenever we detect that this is happening, so we could
only begin, roll back, and commit transactions after verifying that the
transaction count on the server is what we expect at that point in time....
On the other hand this could be even more damaging...

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

>> I'm interested in Microsoft's response.  Does anyone know what the JDBC
>> spec says here?  Does it say "commit" and "rollback"  and other SQL
[quoted text clipped - 54 lines]
>>>
>>>>Thank you for helping us get back on the road.
Joe Weinstein - 25 Jan 2006 02:13 GMT
> We will definitely be looking at this and the separate issue with
> exceptions, I am glad to hear that the inmediate issue at least is resolved.
>
> I can't think of a single driver in existance today for Sql Server that
> handles both TSQL and API transaction handling simultaneously,

For *any* DBMS, and I work on Oracle's thin driver and Sybase's
jConnect driver regularly, as well as debugging ours for DB2, etc.

> making this
> scenario work is going to be very tough. One thing we _could_ do would be to
> throw an exception whenever we detect that this is happening, so we could
> only begin, roll back, and commit transactions after verifying that the
> transaction count on the server is what we expect at that point in time....
> On the other hand this could be even more damaging...

It would drive you nuts. You would have to postpend every execute with a
query to return @@trancount and process it before the next execute from any
statement, which might mean buffering tons of data etc, or even allowing
a fetch from any other sensitive cursor. or even allowing the current
statement to process output parameters. What if the SQL raised a fatal
error after committing? You wouldn't get your post-pended @@trancount
query.

"create proc my_tx_handle @whichway int as begin if (@whichway > 0)commit tran else rollback end"

"create proc my_big_tx as begin select * from the universe exec my_tx_handle 1 end"

and before processing the result set from my_big_tx the user runs another statement...
etc.

And let's assume you're processing in autoCommit(true) mode, and
suddenly you discover @@trancount is 3. What will the driver do?
The fact is that there can only be one controller of the tx state,
and if the driver isn't it, there is no way the driver can choose
what to do if/when it finds it's "not in Kansas anymore". You can
go only so far in protecting the user from himself without causing
trouble for the normal case.
Joe
Joe Weinstein - 22 Jan 2006 19:20 GMT
> Surely the driver can do "set implicit_transactions on" instead of
> that. My old driver from '96 does this:
[quoted text clipped - 5 lines]
>
> Joe Weinstein at BEA Systems

And just to be clear, we consciously chose to roll back any tx context that
was not explicitly committed before a call to setAutoCommit(true). Some
folks are used to Oracle's SQL-PLUS application committing on close, so
you *could* have a connection configuration option to go the other way,
but *boy* is that odd/ugly as desired behavior.
   For both polarities of the call, we do *not* send duplicate/redundant
calls. The driver keeps a flag of the setting it's supposed to be
manifesting, so whenever the user calls setAutoCommit() asking for the
same mode we're already in, we do nothing.
Joe
Jerry Brenner - 20 Jan 2006 22:16 GMT
I'm confused by:

> What this means is that the following scenario would behave
>
[quoted text clipped - 4 lines]
> //insert data 2
> //COMMIT

If the exception from the 1st insert was a statement level exception (like
duplicate key violation), then it is up to the caller to decide what to do.  
If the caller wants to continue, or even just call commit(), then they should
be allowed to do so.  However, if the exception was a transaction level
exception or more severe, then a rollback should occur.   Either way,
autocommit should remain off on the connection, so the caller should be able
to call commit() immediately.
Wes Clark - 20 Jan 2006 22:40 GMT
     conn.setAutoCommit(false);
     conn.commit();
     System.out.println("Commit 1 succeeded");
     conn.commit();
     System.out.println("Commit 2 succeeded");

returns

Commit 1 succeeded
Commit 2 succeeded

and no errors
Joe Weinstein - 20 Jan 2006 22:46 GMT
> I'm confused by:
>
[quoted text clipped - 14 lines]
> autocommit should remain off on the connection, so the caller should be able
> to call commit() immediately.

Right. We can cobble up an exampel with two connections and provoke a
simple deadlock between them. One of them will get it's tx aborted,
and we should then see whether an immediate commit() and/or rollback()
gives a problem. Yes, the driver and DBMS should both still be in
chained/implicit transaction/autoCommit(false) mode.
Joe
Joe Weinstein - 20 Jan 2006 23:08 GMT
> I'm confused by:
>
[quoted text clipped - 14 lines]
> autocommit should remain off on the connection, so the caller should be able
> to call commit() immediately.

I ran the program below, in two windows, the first like:

C:\> java two_cons start

when it said to run the second, I did, like:

and the other:

C:\> java two_cons

This set up a deadlock to happen. When the second program said to press return in the first's window,
I did, and it got the deadlock message. Then I checked the autoCommit() status, which was
still false as far as the driver was concerned at least, and a final commit() on the connection
got an exception:

trying commit...
com.microsoft.sqlserver.jdbc.SQLServerException: Server failed to resume the transaction, desc:
  3300000007.
        at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source
)
        at com.microsoft.sqlserver.jdbc.IOBuffer.processPackets(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectionCommand(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.sendCommit(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.commit(Unknown Source)
        at two_cons.main(two_cons.java:66)

Program:
import java.sql.*;
import java.util.*;

public class two_cons
{
    public static void main(String args[])
        throws Exception
    {
        Connection c = null;
        try
        {
          Properties props = new Properties();
          Driver d = new com.microsoft.sqlserver.jdbc.SQLServerDriver();

          props.put("user",     "joe");
          props.put("password", "joe");
          props.put("DatabaseName", "joe");

          c = d.connect("jdbc:sqlserver://joe:1433", props );

          DatabaseMetaData dd = c.getMetaData();
          System.out.println("Driver version is " + dd.getDriverVersion() );

          Statement s = c.createStatement();

if (args.length != 0)
{
          try {s.executeUpdate("drop table joe");}catch (Exception ignore){}
          try {s.executeUpdate("drop table joe2");}catch (Exception ignore){}
          s.executeUpdate("create table joe(foo int)");
          s.executeUpdate("insert joe values(1)");
          s.executeUpdate("create table joe2(foo int)");
          s.executeUpdate("insert joe2 values(1)");

          c.setAutoCommit(false);
          s.executeUpdate("update joe set foo = 2");

System.out.println("Ok, now run the other and press return");
System.in.read();
          s.executeUpdate("update joe2 set foo = 2");
}
else
{
          c.setAutoCommit(false);
          s.executeUpdate("update joe2 set foo = 2");
System.out.println("Ok, now press return on the other");

          s.executeUpdate("update joe set foo = 2");
}
        }
        catch(Exception exception1)
        {
            exception1.printStackTrace();
        }
        finally
        {
            try {
              System.out.println("c.getAutoCommit() says " + c.getAutoCommit() );
            } catch (Exception ee) {
               ee.printStackTrace();
            }

            try {
              System.out.println("trying commit..." );
              c.commit();
            } catch (Exception ee) {
               ee.printStackTrace();
            }
            if (c != null) try {c.close();} catch (Exception ignore){}
        }
    }
}
Joe Weinstein - 20 Jan 2006 23:12 GMT
Oh, and if I changed the program to try to
rollback instead of commit, there was *still*
a problem! There's a bug. The tx *did* get
rolled back because it was the deadlock victim,
but as far as JDBC is concerned, the user's tx
got some sort of exception, and he wants to rollback()
on an autoCommit(false) connection and should
be able to.
Joe Weinstein at BEA Systems

>> I'm confused by:
>>
[quoted text clipped - 130 lines]
>     }
> }
Angel Saenz-Badillos[MS] - 20 Jan 2006 23:23 GMT
Rolling back we should not see that problem, I would be very interested in
getting that to repro.

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

> Oh, and if I changed the program to try to
> rollback instead of commit, there was *still*
[quoted text clipped - 140 lines]
>>     }
>> }
Jerry Brenner - 20 Jan 2006 23:49 GMT
I turned on the SQL Profiler and the only error that occurs is the 3902 that
we are complaining about.  There are no exceptions prior to that.  Joe's
program demonstrates a serious bug, but it looks we are hitting a different
bug.  Unfortunately, I we haven't been able to figure out how this unit test
is different than any of the other ones that aren't failing.
Angel Saenz-Badillos[MS] - 21 Jan 2006 00:11 GMT
Jerry,
Thank you for taking the time to go through this. It sounds like you have a
very comprehensive testing framework, if you are interested we would be
happy to work with you to work through these and future issues. Feel free to
contact me at the above email address (without the "online").

Signature

Angel Saenz-Badillos [MS] DataWorks
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging: http://weblogs.asp.net/angelsb/

>I turned on the SQL Profiler and the only error that occurs is the 3902
>that
[quoted text clipped - 4 lines]
> test
> is different than any of the other ones that aren't failing.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2010 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.