[
https://issues.apache.org/jira/browse/DERBY-4279?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13403101#comment-13403101
]
Brett Wooldridge commented on DERBY-4279:
-----------------------------------------
Kristian,
None of this is documented obviously, but here is my best guess why that code
is the way that it is. Trying to open the conglomerate acts as a check that
the schema has not been modified by another thread/transaction. There may be
other locks in place, as you mentioned, that attempt to prevent DDL run running
but my guess is there are still 'seams' where it can happen. Hence the opening
of the conglomerate, and note also (especially) the comments in the try...catch
in GenericStatement.prepare() where the StandardException is caught and
explicitly checked for an error. The comment is:
// There is a chance that we didn't see the invalidation
// request from a DDL operation in another thread because
// the statement wasn't registered as a dependent until
// after the invalidation had been completed. Assume that's
// what has happened if we see a conglomerate does not exist
// error...
Which implies to me that DDL might not always be blocked, and code was put in
place to handle that case. Since DDL is rare in a running system, catching an
exception might therefore be much cheaper than some kind of read/write lock to
try to prevent it.
The other possibility is that DDL and DML are completely protected/synchronized
now (compared to when that code was written), and some of that code is simply
unnecessary. I'm not in a position to make that judgement. Hence my attempt
to retain as much as of the original behavior, be it inefficient or not, to
minimize side-effects.
I would be perfectly happy with the patch as submitted along with additional
comments in the code basically asking 'Is the still necessary?' with a
reference to this bug. Maybe at some point in the future someone digging
through the code will unravel the logic completely and determine that 'yes, it
is necessary' or 'no, it is not'.
> Statement cache deadlock
> ------------------------
>
> Key: DERBY-4279
> URL: https://issues.apache.org/jira/browse/DERBY-4279
> Project: Derby
> Issue Type: Bug
> Components: SQL
> Affects Versions: 10.0.2.1, 10.1.3.1, 10.2.2.0, 10.3.3.0, 10.4.2.0,
> 10.5.1.1, 10.8.1.2
> Environment: Windows Vista, OS X 10.5+
> Reporter: Jeff Stuckman
> Labels: derby_triage10_5_2
> Attachments: Derby4279.java, client_stacktrace_activation_closed.txt,
> no-lock-experiment.diff, patch4279.txt, patch4279_2.txt, stacktrace.txt
>
>
> Due to a design flaw in the statement cache, a deadlock can occur if a
> prepared statement becomes out-of-date.
> I will illustrate this with the following example:
> The application is using the embedded Derby driver. The application has two
> threads, and each thread uses its own connection.
> There is a table named MYTABLE with column MYCOLUMN.
> 1. A thread prepares and executes the query SELECT MYCOLUMN FROM MYTABLE. The
> prepared statement is stored in the statement cache (see
> org.apache.derby.impl.sql.GenericStatement for this logic)
> 2. After some time, the prepared statement becomes invalid or out-of-date for
> some reason (see org.apache.derby.impl.sql.GenericPreparedStatement)
> 3. Thread 1 begins a transaction and executes LOCK TABLE MYTABLE IN EXCLUSIVE
> MODE
> 4. Thread 2 begins a transaction and executes SELECT MYCOLUMN FROM MYTABLE.
> The statement is in the statement cache but it is out-of-date. The thread
> begins to recompile the statement. To compile the statement, the thread needs
> a shared lock on MYTABLE. Thread 1 already has an exclusive lock on MYTABLE.
> Thread 2 waits.
> 5. Thread 1 executes SELECT MYCOLUMN FROM MYTABLE. The statement is in the
> statement cache but it is being compiled. Thread 1 waits on the statement's
> monitor.
> 6. We have a deadlock. Derby eventually detects a lock timeout, but the error
> message is not descriptive. The stacks at the time of the deadlock are:
> This deadlock is unique because it can still occur in a properly designed
> database. You are only safe if all of your transactions are very simple and
> cannot be interleaved in a sequence that causes the deadlock, or if your
> particular statements do not require a table lock to compile. (For the sake
> of simplicity, I used LOCK TABLE in my example, but any UPDATE statement
> would fit.)
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira