[
https://issues.apache.org/jira/browse/DERBY-6554?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Rick Hillegas updated DERBY-6554:
---------------------------------
Attachment: derby-6554-01-ac-useCreationTransaction.diff
Thanks, Mike. We may need to ask for your help in pushing this problem into the
Store if people think that the following solution is too complex.
Attaching derby-6554-01-ac-useCreationTransaction.diff. This patch attempts to
address the D6554 problem case. This patch also addresses some other problems
discovered while investigating D6554. I am running tests now.
The solution, including the fix for D6554, now is:
1) Remember the transaction id which created the sequence. This is saved in the
SequenceUpdater which corresponds to the new sequence.
2) A map of (sequenceID, creatingTransactionID) pairs is maintained so that we
can restore the SequenceUpdater's creatingTransactionID after cache eviction.
The map is not persistent. Rebooting the database clears it out.
3) A good faith effort is made to garbage collect a (sequenceID,
creatingTransactionID) pair and keep the map from growing indefinitely.
However, there are cases when we won't know that it's ok to garbage collect a
pair. I considered putting a hard limit on the size of the map. But I think
that is brittle, particularly since I can't guarantee that the pair will
eventually be garbage collected. This means that there is a
resource-leak/denial-of-service defect with this solution. I think it is
unlikely that any well behaved application will see this problem. And it is not
clear to me that this is really a new vulnerability: in setting up such a
situation, it is possible that you will hit some other resource limit first.
But if people think this is a serious defect, then we will have to consider
something fancier or abandon this approach.
In developing this fix for D6554, I tripped across a bug in cache eviction: If
there was an uncommitted CREATE SEQUENCE holding a lock on a SYS.SYSSEQUENCES
row at cache eviction time, and the cache evicting transaction was not the
transaction which created the sequence, then the Cacheable.clean() method would
raise an exception when trying to flush the unused sequence values to disk.
This, in turn, would short-circuit the clearing of the Cacheable identity. And
that would raise an assertion when the Cacheable was re-used: "Identity being
changed on a live cacheable". To fix this, I have moved the identity-resetting
logic into a finally block.
Developing the fix for D6554 also concentrated my attention on this behavior of
sequence generators: If a sequence generator is evicted from the cache and the
evicting transaction can't write to SYS.SYSSEQUENCES, then gaps in the sequence
will appear. I'm aware of only two situations which give rise to this problem:
1) An uncommitted CREATE SEQUENCE statement.
2) Users who ignore our advice and scan SYS.SYSSEQUENCES.
Finally, in order to reduce the likelihood that we will trip across cache
eviction problems, I have increased the size of the sequence generator cache to
1000. Applications will need to adjust
derby.language.sequenceGeneratorCacheSize if they need to create and use a lot
of sequences in a single transaction.
Touches the following additional file:
M java/engine/org/apache/derby/iapi/reference/Property.java
> Too much contention followed by assert failure when accessing sequence in
> transaction that created it
> -----------------------------------------------------------------------------------------------------
>
> Key: DERBY-6554
> URL: https://issues.apache.org/jira/browse/DERBY-6554
> Project: Derby
> Issue Type: Bug
> Components: SQL
> Affects Versions: 10.9.1.0, 10.11.0.0, 10.10.2.0
> Reporter: Knut Anders Hatlen
> Attachments: D6554.java,
> derby-6554-01-aa-useCreationTransaction.diff,
> derby-6554-01-ab-useCreationTransaction.diff,
> derby-6554-01-ac-useCreationTransaction.diff
>
>
> {noformat}
> ij version 10.11
> ij> connect 'jdbc:derby:memory:db;create=true' as c1;
> ij> autocommit off;
> ij> create sequence seq;
> 0 rows inserted/updated/deleted
> ij> values next value for seq;
> 1
> -----------
> ERROR X0Y84: Too much contention on sequence SEQ. This is probably caused by
> an uncommitted scan of the SYS.SYSSEQUENCES catalog. Do not query this
> catalog directly. Instead, use the SYSCS_UTIL.SYSCS_PEEK_AT_SEQUENCE function
> to view the current value of a query generator.
> ij> rollback;
> ERROR 08003: No current connection.
> ij> connect 'jdbc:derby:memory:db' as c2;
> ij(C2)> autocommit off;
> ij(C2)> create sequence seq;
> 0 rows inserted/updated/deleted
> ij(C2)> values next value for seq;
> 1
> -----------
> ERROR 38000: The exception
> 'org.apache.derby.shared.common.sanity.AssertFailure: ASSERT FAILED Identity
> being changed on a live cacheable. Old uuidString =
> 0ddd00a9-0145-98ba-79df-000007d88b08' was thrown while evaluating an
> expression.
> ERROR XJ001: Java exception: 'ASSERT FAILED Identity being changed on a live
> cacheable. Old uuidString = 0ddd00a9-0145-98ba-79df-000007d88b08:
> org.apache.derby.shared.common.sanity.AssertFailure'.
> {noformat}
--
This message was sent by Atlassian JIRA
(v6.2#6252)