Fixed ALF-11946: Lucene index recovery startup can cause full table scans and file sorts

- Made the backward timestepping work in bounded segments, whereas previously there
   was no lower bound causing the database to creak under load and the whole process
   to take a long time.
 - Seen during benchmark testing as well


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32659 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2011-12-09 02:14:55 +00:00
parent 25382b991f
commit 0245b34542

View File

@@ -404,11 +404,17 @@ public class IndexTransactionTracker extends AbstractReindexComponent
*/ */
protected long getStartingTxnCommitTime() protected long getStartingTxnCommitTime()
{ {
Long minTxnCommitTimeMs = nodeDAO.getMinTxnCommitTime();
if (minTxnCommitTimeMs == null)
{
return 0L;
}
long dontSearchBeforeMs = minTxnCommitTimeMs - 1L;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
// Get the last indexed transaction for all transactions // Get the last indexed transaction for all transactions
long lastIndexedAllCommitTimeMs = getLastIndexedCommitTime(now, false); long lastIndexedAllCommitTimeMs = getLastIndexedCommitTime(dontSearchBeforeMs, now, false);
// Now check back from this time to make sure there are no remote transactions that weren't indexed // Now check back from this time to make sure there are no remote transactions that weren't indexed
long lastIndexedRemoteCommitTimeMs = getLastIndexedCommitTime(now, true); long lastIndexedRemoteCommitTimeMs = getLastIndexedCommitTime(dontSearchBeforeMs, now, true);
// The one to start at is the least of the two times // The one to start at is the least of the two times
long startTime = Math.min(lastIndexedAllCommitTimeMs, lastIndexedRemoteCommitTimeMs); long startTime = Math.min(lastIndexedAllCommitTimeMs, lastIndexedRemoteCommitTimeMs);
// Done // Done
@@ -419,25 +425,33 @@ public class IndexTransactionTracker extends AbstractReindexComponent
* Gets the commit time for the last indexed transaction. If there are no transactions, then the * Gets the commit time for the last indexed transaction. If there are no transactions, then the
* current time is returned. * current time is returned.
* *
* @param dontSearchBeforeMs the time to stop looking i.e. there will not be transaction before this
* @param maxCommitTimeMs the largest commit time to consider * @param maxCommitTimeMs the largest commit time to consider
* @param remoteOnly <tt>true</tt> to only look at remotely-committed transactions * @param remoteOnly <tt>true</tt> to only look at remotely-committed transactions
* @return Returns the last indexed transaction commit time for all or * @return Returns the last indexed transaction commit time for all or
* remote-only transactions. * remote-only transactions.
*/ */
private long getLastIndexedCommitTime(long maxCommitTimeMs, boolean remoteOnly) private long getLastIndexedCommitTime(long dontSearchBeforeMs, long maxCommitTimeMs, boolean remoteOnly)
{ {
// Look back in time by the maximum transaction duration // Look back in time by the maximum transaction duration
long maxToTimeExclusive = maxCommitTimeMs - maxTxnDurationMs; long maxToTimeExclusive = maxCommitTimeMs - maxTxnDurationMs;
long toTimeExclusive = maxToTimeExclusive; long toTimeExclusive = maxToTimeExclusive;
long fromTimeInclusive = 0L; long fromTimeInclusive = toTimeExclusive;
double stepFactor = 1.0D; double stepFactor = 1.0D;
boolean firstWasInIndex = true; boolean firstWasInIndex = true;
found: found:
while (true) while (fromTimeInclusive > dontSearchBeforeMs)
{ {
// Get the most recent transaction before the given look-back toTimeExclusive = fromTimeInclusive;
// Look further back in time. Step back by 60 seconds each time, increasing
// the step by 10% each iteration.
// Don't step back by more than an hour
long decrement = Math.min(ONE_HOUR_MS, (long) (60000.0D * stepFactor));
fromTimeInclusive -= decrement;
// Try to find a transaction near to the time
List<Transaction> nextTransactions = nodeDAO.getTxnsByCommitTimeDescending( List<Transaction> nextTransactions = nodeDAO.getTxnsByCommitTimeDescending(
0L, fromTimeInclusive,
toTimeExclusive, toTimeExclusive,
1, 1,
null, null,
@@ -445,7 +459,8 @@ found:
// There are no transactions in that time range // There are no transactions in that time range
if (nextTransactions.size() == 0) if (nextTransactions.size() == 0)
{ {
break found; stepFactor *= 1.1D;
continue;
} }
// We found a transaction // We found a transaction
Transaction txn = nextTransactions.get(0); Transaction txn = nextTransactions.get(0);
@@ -458,17 +473,13 @@ found:
fromTimeInclusive = txnCommitTime; fromTimeInclusive = txnCommitTime;
break found; break found;
case INDETERMINATE: case INDETERMINATE:
// If we hit an indeterminate transaction we go back a small amount to try and hit something definitive before a bigger step back
firstWasInIndex = false; firstWasInIndex = false;
toTimeExclusive = txnCommitTime - 1000; // If we hit an indeterminate transaction we go back to small backward steps
stepFactor = 1.0D;
continue; continue;
default: default:
firstWasInIndex = false; firstWasInIndex = false;
// Look further back in time. Step back by 60 seconds each time, increasing // Start increasing steps backwards
// the step by 10% each iteration.
// Don't step back by more than an hour
long decrement = Math.min(ONE_HOUR_MS, (long) (60000.0D * stepFactor));
toTimeExclusive = txnCommitTime - decrement;
stepFactor *= 1.1D; stepFactor *= 1.1D;
continue; continue;
} }