It is triggered when we try to add rows to SYS.SYSCOLUMNS in DataDictionaryImpl.updateSPS():
/*beetle:5119, reason for doing add here instead of update
*is with NOCOMPILE option of create statement/boot time SPS,
*SPS statement is not compiled to find out the parameter info.
*Because of the parameter info was not inserted at SPSDescriptor
*creation time. As this is the first time we are compiling paramter
*infor should be inserted instead of the update.
For some reason the rows already exist, even though the meta-data statement has not been compiled before.
I'm wondering if this is related to the retry logic in SPSDescriptor.getPreparedStatement(boolean):
DERBY-2584: If the first attempt to compile the query fails,
// we need to reset initiallyCompilable to make sure the
// prepared plan is fully stored to disk. Save the initial
// value here.
final boolean compilable = initiallyCompilable;
prepareAndRelease(lcc, null, nestedTC);
updateSYSSTATEMENTS(lcc, RECOMPILE, nestedTC);
catch (StandardException se)
if (nestedTC != null)
nestedTC = null;
// if we couldn't do this with a nested xaction, retry with
// parent-- we need to wait this time!
initiallyCompilable = compilable;
prepareAndRelease(lcc, null, null);
updateSYSSTATEMENTS(lcc, RECOMPILE, null);
else throw se;
If the lock timeout in the nested transaction happens after addSPSParams() has been called, the rows will be there when we retry the operation in the user transaction since we commit the nested transaction instead of aborting it. I think we can't abort the nested transaction because it will also abort the parent transaction, but perhaps it is possible to use savepoints to make sure that all the changes made by the nested transaction are rolled back before we retry.