[
https://issues.apache.org/jira/browse/DERBY-4343?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12740453#action_12740453
]
Kristian Waagan commented on DERBY-4343:
----------------------------------------
I believe I understand why the assert happens.
When obtaining the pooled connection for the third time, the variable
isolation_ is reset by the following code in Connection.completeReset:
if (closeStatementsOnClose) {
// NOTE: This is to match previous behavior.
// Investigate and check if it is really necessary.
this.isolation_ = TRANSACTION_UNKNOWN;
java.util.Set keySet = openStatements_.keySet();
for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
Object o = i.next();
((Statement) o).reset(closeStatementsOnClose);
}
} else {
When setTransactionIsolation is called, and actually executed, the server
doesn't send any piggybacked update because the level hasn't changed. This
means the isolation_ will remain as UNKNOWN until getTransactionIsolation is
called or a different statement causing a change of the isolation level is
executed.
DERBY-4314 causes the assert to never be reached by (in this case) querying the
server about the isolation level and then short-circuiting
setTransactionIsolation:
+ // Derby-4314 fix, the client driver should acted like embedded
+ if (level == getTransactionIsolationX())
+ return;
For completeness, removing the return in this case would also make the assert
pass, since getTransactionIsolationX would have updated the value of isolation_.
My take on this assert is that it is doesn't have any consequences "in the real
world". Next time the user asks for the isolation level, it will be fetched
from the server and a correct value will be returned.
I'm +1 for patch DERBY-4314-5.diff, but I'm not yet confident resetting the
value to READ_COMMITTED is the best solution (as of today, I think it is a
correct change though).
The patch won't improve the performance, it will just move the round-trip. In
some cases I believe it will make it worse for the initial
setTransactionIsolation call, depending on whether the value being set is
READ_COMMITTED or not. If it is, we still get one round-trip (check +
short-circuit), but if it isn't we get two (check + change).
Note that the situation is slightly different when the client side JDBC
statement cache is enabled.
This means that for better performance, we need additional changes.
Not thinking ahead, the simplest change would be to assume that the default
isolation level will be READ_COMMITTED for ever. If this turns out to be false
in the future, we may get out of it using version checks.
A better, but more demanding solution, would be to obtain the default isolation
level at initial connection time, for instance using the existing piggybacking
feature. This still requires a version check in the server, but gives us more
flexibility [1].
On top of this we have the XA scenario, which I understand requires some extra
care to avoid returning stale/incorrect values.
Thoughts?
[1] I'm thinking about optimizing this situation in Connection.completeReset:
} else {
// Must reset transaction isolation level if it has been changed.
if (isolation_ != Connection.TRANSACTION_READ_COMMITTED) {
// This might not fare well with connection pools, if it has
// been configured to deliver connection with a different
// isolation level, i.e. it has to set the isolation level again
// when it returns connection to client.
// TODO: Investigate optimization options.
setTransactionIsolationX(Connection.TRANSACTION_READ_COMMITTED);
}
With the described approach, the default level could be configured in the
connection url with an attribute. I do not know if this is allowed by the
relevant standards, or if it is something we ever want to do.
> ASSERT FAILED calling setTransactionIsolation checking isolation_ == level
> on pooled connection
> --------------------------------------------------------------------------------------------------
>
> Key: DERBY-4343
> URL: https://issues.apache.org/jira/browse/DERBY-4343
> Project: Derby
> Issue Type: Bug
> Components: JDBC, Network Client
> Affects Versions: 10.6.0.0
> Reporter: Kathey Marsden
> Attachments: TestConnReuse.java
>
>
> For DERBY-4314, I thought I would do a little testing to understand the
> server round trips in various scenarios for pooled connections. So I wrote
> the small attached program ConnReuse.java and hit this assertion in client:
> Exception in thread "main"
> org.apache.derby.shared.common.sanity.AssertFailure: ASSERT FAILED
> at
> org.apache.derby.shared.common.sanity.SanityManager.ASSERT(SanityManager.java:98)
> at
> org.apache.derby.client.am.Connection.setTransactionIsolationX(Connection.java:987)
> at
> org.apache.derby.client.am.Connection.setTransactionIsolation(Connection.java:915)
> at
> org.apache.derby.client.am.LogicalConnection.setTransactionIsolation(LogicalConnection.java:253)
> at TestConnReuse.main(TestConnReuse.java:32)
> ---------------
> To run the program on trunk:
> java org.apache.derby.drda.NetworkServerControl start
> java TestConnReuse.
> This needs more investigation, but I thought I would go ahead and log the
> bug. I tried this only on trunk. I have not yet
> - Tried it on the branches.
> - Tried it with Lily's DERBY-4314 patch.
> - Tried it with embedded.
> - Tried actually doing something with the prior logical connection which
> might be related.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.