db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Knut Anders Hatlen (JIRA)" <j...@apache.org>
Subject [jira] Commented: (DERBY-4279) Statement cache deadlock
Date Fri, 11 Jun 2010 09:53:13 GMT

    [ https://issues.apache.org/jira/browse/DERBY-4279?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12877761#action_12877761
] 

Knut Anders Hatlen commented on DERBY-4279:
-------------------------------------------

Hi Brett,

Thanks for contributing the patch. I think creating a new statement instead of waiting sounds
like a reasonable approach to solve this bug.

I have a couple of questions about the patch:

1) The synchronized block in GenericActivationHolder.execute() is expanded. What's the reasoning
behind this change?

2) In GenericStatement, I noticed that the old code that generates a new statement if the
session schema is references, sets foundInCache to false to prevent the call to removeStatement()
in catch blocks further down. Should we do the same in the new code that checks the value
of compilingStatement? I'm not sure if calling removeStatement() on a statement that's not
in the cache does any harm, but I thought I'd mention it in any case.

3) Since the patch removes the call to wait() on the prepared statement (the only call to
wait() as far as I can tell), do you think it would be safe to also remove the calls to notifyAll()
in GenericStatement and GenericPreparedStatement?

> 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
>         Environment: Windows Vista
>            Reporter: Jeff Stuckman
>            Assignee: Brett Wooldridge
>         Attachments: Derby4279.java, patch4279.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.
-
You can reply to this email to add a comment to the issue online.


Mime
View raw message