[ 
https://issues.apache.org/jira/browse/DERBY-6975?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

David Sitsky updated DERBY-6975:
--------------------------------
    Description: 
I have an application that when run on a certain dataset, every 5 runs I might 
see this error happening.  The code is creating a lot of rows using a sequence 
generator.
{noformat}
Caused by: ERROR 40XL1: A lock could not be obtained within the time requested 
        at 
org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
 
        at 
org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
 
        at 
org.apache.derby.impl.sql.catalog.SequenceUpdater.tooMuchContentionException(SequenceUpdater.java)
 
        at 
org.apache.derby.impl.sql.catalog.SequenceUpdater.getCurrentValueAndAdvance(SequenceUpdater.java)
 
        at 
org.apache.derby.impl.sql.catalog.DataDictionaryImpl.getCurrentValueAndAdvance(DataDictionaryImpl.java)
 
        at 
org.apache.derby.impl.sql.execute.BaseActivation.getCurrentValueAndAdvance(BaseActivation.java)
 
        at 
org.apache.derby.impl.sql.execute.InsertResultSet.getSetAutoincrementValue(InsertResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.BaseActivation.getSetAutoincrementValue(BaseActivation.java)
 
        at 
org.apache.derby.exe.ac560740aax015fx6bc1x68cax000002339e626a.e0(ac560740aax015fx6bc1x68cax000002339e626a.java)
 
        at 
org.apache.derby.impl.services.reflect.DirectCall.invoke(DirectCall.java) 
        at 
org.apache.derby.impl.sql.execute.RowResultSet.getNextRowCore(RowResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.InsertResultSet.getNextRowCore(InsertResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java) 
        at 
org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java)
 
        at 
org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java)
 
        ... 25 more 
{noformat}
It is not clear to me why when looking at the code this should be happening.  

  was:
I have an application that sporadically gets this exception when inserting a 
lot of rows using a sequence generator.
{noformat}
Caused by: ERROR 40XL1: A lock could not be obtained within the time requested 
        at 
org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
 
        at 
org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
 
        at 
org.apache.derby.impl.sql.catalog.SequenceUpdater.tooMuchContentionException(SequenceUpdater.java)
 
        at 
org.apache.derby.impl.sql.catalog.SequenceUpdater.getCurrentValueAndAdvance(SequenceUpdater.java)
 
        at 
org.apache.derby.impl.sql.catalog.DataDictionaryImpl.getCurrentValueAndAdvance(DataDictionaryImpl.java)
 
        at 
org.apache.derby.impl.sql.execute.BaseActivation.getCurrentValueAndAdvance(BaseActivation.java)
 
        at 
org.apache.derby.impl.sql.execute.InsertResultSet.getSetAutoincrementValue(InsertResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.BaseActivation.getSetAutoincrementValue(BaseActivation.java)
 
        at 
org.apache.derby.exe.ac560740aax015fx6bc1x68cax000002339e626a.e0(ac560740aax015fx6bc1x68cax000002339e626a.java)
 
        at 
org.apache.derby.impl.services.reflect.DirectCall.invoke(DirectCall.java) 
        at 
org.apache.derby.impl.sql.execute.RowResultSet.getNextRowCore(RowResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.InsertResultSet.getNextRowCore(InsertResultSet.java)
 
        at 
org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java) 
        at 
org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java)
 
        at 
org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java)
 
        ... 25 more 
{noformat}
When I look at the code in question, it comes down to this method:
{code}
    /**
     * <p>
     * Get the next sequence number managed by this generator and advance the 
number. Could raise an
     * exception if the legal range is exhausted and wrap-around is not allowed.
     * Only one thread at a time is allowed through here. We do not want a race 
between the
     * two calls to the sequence generator: getCurrentValueAndAdvance() and 
allocateNewRange().
     * </p>
     *
     * @param returnValue This value is stuffed with the new sequence number.
     */
    public synchronized void getCurrentValueAndAdvance
        ( NumberDataValue returnValue ) throws StandardException
    {
        //
        // We may have to try to get a value from the Sequence Generator twice.
        // The first attempt may fail because we need to pre-allocate a new 
chunk
        // of values.
        //
        for ( int i = 0; i < 2; i++ )
        {
            //
            // We try to get a sequence number. The SequenceGenerator method is 
synchronized
            // so only one writer should be in there at a time. Lock contention 
is possible if
            // someone has selected from SYSSEQUENCES contrary to our advice. 
In that case,
            // we raise a TOO MUCH CONTENTION exception.
            //
            long[] cvaa = _sequenceGenerator.getCurrentValueAndAdvance();
            
            int status = (int) cvaa[ SequenceGenerator.CVAA_STATUS ];
            long currentValue = cvaa[ SequenceGenerator.CVAA_CURRENT_VALUE ];
            long lastAllocatedValue = cvaa[ 
SequenceGenerator.CVAA_LAST_ALLOCATED_VALUE ];
            long numberOfValuesAllocated = cvaa[ 
SequenceGenerator.CVAA_NUMBER_OF_VALUES_ALLOCATED ];
            
            switch ( status )
            {
            case SequenceGenerator.RET_OK:
                returnValue.setValue( currentValue );
                return;
                
            case SequenceGenerator.RET_MARK_EXHAUSTED:
                updateCurrentValueOnDisk( currentValue, null );
                returnValue.setValue( currentValue );
                return;
                
            case SequenceGenerator.RET_ALLOCATE_NEW_VALUES:
                
                if ( updateCurrentValueOnDisk( currentValue, lastAllocatedValue 
) )
                {
                    _sequenceGenerator.allocateNewRange( currentValue, 
numberOfValuesAllocated );
                }
                break;
            
            default:
                throw unimplementedFeature();
            }
        }

        //
        // If we get here, then we failed to allocate a new sequence number 
range.
        //
        throw tooMuchContentionException();
    }
{code}
If I understand the intent of this code, in the 
SequenceGenerator.RET_ALLOCATE_NEW_VALUES case, we allocate a new sequence 
generator range and then we are meant to re-execute the loop again to use it, 
however since "break" is used we break out of the for loop and throw the 
exception.

It seems if we replace "break" with 'continue" this will work as expected?


> ERROR 40XL1: A lock could not be obtained within the time requested 
> --------------------------------------------------------------------
>
>                 Key: DERBY-6975
>                 URL: https://issues.apache.org/jira/browse/DERBY-6975
>             Project: Derby
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions: 10.14.1.0
>            Reporter: David Sitsky
>         Attachments: fix.patch
>
>
> I have an application that when run on a certain dataset, every 5 runs I 
> might see this error happening.  The code is creating a lot of rows using a 
> sequence generator.
> {noformat}
> Caused by: ERROR 40XL1: A lock could not be obtained within the time 
> requested 
>         at 
> org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
>  
>         at 
> org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
>  
>         at 
> org.apache.derby.impl.sql.catalog.SequenceUpdater.tooMuchContentionException(SequenceUpdater.java)
>  
>         at 
> org.apache.derby.impl.sql.catalog.SequenceUpdater.getCurrentValueAndAdvance(SequenceUpdater.java)
>  
>         at 
> org.apache.derby.impl.sql.catalog.DataDictionaryImpl.getCurrentValueAndAdvance(DataDictionaryImpl.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.BaseActivation.getCurrentValueAndAdvance(BaseActivation.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.InsertResultSet.getSetAutoincrementValue(InsertResultSet.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.BaseActivation.getSetAutoincrementValue(BaseActivation.java)
>  
>         at 
> org.apache.derby.exe.ac560740aax015fx6bc1x68cax000002339e626a.e0(ac560740aax015fx6bc1x68cax000002339e626a.java)
>  
>         at 
> org.apache.derby.impl.services.reflect.DirectCall.invoke(DirectCall.java) 
>         at 
> org.apache.derby.impl.sql.execute.RowResultSet.getNextRowCore(RowResultSet.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.InsertResultSet.getNextRowCore(InsertResultSet.java)
>  
>         at 
> org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java) 
>         at 
> org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java)
>  
>         at 
> org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java)
>  
>         ... 25 more 
> {noformat}
> It is not clear to me why when looking at the code this should be happening.  



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to