I'm having a couple of issues with using Oracle and JDBC.
Environment:
Windows XP Pro
j2sdk1.4.2_07
Oracle JDBC Driver version - 10.1.0.2.0
Server: Oracle 9i Enterprise Ed Release 0.2.0.1.0 - Production
Now that I have that out of the way, here are my problems:
I have broken the code into small parts, the entire code can be viewed
here:
http://rafb.net/paste/results/hvsrN259.html
Note, this is just a simple program I wrote to help demonstrate the
issues I have. It is not production code, just trying to test some
stuff.
Ok, I've successfully retrieved my connection, and now I'm setting
auto commit to false, and I don't want to read data unless its been
committed...
connection.setAutoCommit(false);
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
try {
Create a statement for update.
Statement statement =
connection.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
Execute a statement to get the next ID. Now, given that I've set the
connection to TRANSACTION_READ_COMMITTED, I am expecting this to not
allow me to read this if an uncommitted transaction has updated this
row.
statement.execute(
"SELECT MAX(TEST.ID) + 1 AS NEWID FROM TEST");
ResultSet idResultSet = statement.getResultSet();
int id = 1;
if (idResultSet.first()) {
id = idResultSet.getInt(1);
}
Here, I select and get the updatable Rowset, and insert the row.
statement.execute("SELECT TEST.* FROM TEST");
ResultSet resultSet = statement.getResultSet();
resultSet.moveToInsertRow();
resultSet.updateInt(1, id);
resultSet.updateString(2, "TEST" + id);
resultSet.insertRow();
And here I committ.
connection.commit();
} catch (SQLException e) {
connection.rollback();
e.printStackTrace();
}
Ok, in another application (Toad Free), I update the TEST table, but
don't commit.
I run the above application, and it blocks on Line 26
(resultSet.insertRow()). This isn't what I was expecting. I thought it
would block on Line 12 (the first statement.execute()). The
consequence of this is that suppose I inserted a row (5, 'test') in
Toad Free, and didn't commit, then ran the application, and the next
ID is 5, when Toad commits, my application will get a unique
constraint violation.
Second issue is this. I put a break point on line 26
(resultSet.insertRow()). While sitting on this row, I simulate a
network outage by disabling my network. I resume my program, and it
errors out as expected. This issue is that now Oracle has a lock on
the table, and doesn't seem to want to get rid of it. The ONLY way I
could release it was to kill the session in Oracle.
Any ideas what concepts I'm missing? Doing wrong?
Thanks.
--
now with more cowbell
joeNOSPAM@BEA.com - 24 Mar 2005 00:11 GMT
Hi. You need to understand Oracle's locking modes. The connections
will be READ_COMMITTED by default. Oracle will *never* block a
data reader, even is another connection has updated the data but
hasn't committed yet. READ_COMMITTED means the reader will
read the data as it was and is (ie: the old data). The new data is not
committed. The old data is. READ_COMMITTED works that way.
If you want a reader to be blocked form reading anything that is being
updated in another tx, you would need to use the oracle-specific
SELECT ... FOR UPDATE syntax. Even if the reader isn't really going
to update the data, the DBMS won't block the reader unless you give the
DBMS the hin that you want to exclusively lock that read data. Even if
you set the isolation level to SERIALIZABLE, readers won't be blocked
without that syntax.
Joe Weinstein at BEA
Bryce - 24 Mar 2005 16:01 GMT
>Hi. You need to understand Oracle's locking modes. The connections
>will be READ_COMMITTED by default. Oracle will *never* block a
[quoted text clipped - 10 lines]
>without that syntax.
>Joe Weinstein at BEA
Thanks. That makes sense now.
--
now with more cowbell