mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
MNT-22186: propTablesCleanupJobDetail v2 can cause Out of Memory errors (CleanAlfPropTablesV2.sql ) (#390)
- added dialect check to set MySQL specific fetch size limitation (Integer.MIN_VALUE). fetchSize activates result set streaming. - updated tests
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.schema.script;
|
||||
|
||||
import org.alfresco.repo.domain.dialect.Dialect;
|
||||
import org.alfresco.repo.domain.dialect.MySQLInnoDBDialect;
|
||||
import org.alfresco.util.LogUtil;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
@@ -74,6 +76,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
private int line;
|
||||
private File scriptFile;
|
||||
private Properties globalProperties;
|
||||
private Dialect dialect;
|
||||
|
||||
private boolean readOnly;
|
||||
private int deleteBatchSize;
|
||||
@@ -84,12 +87,18 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
private Date startTime;
|
||||
|
||||
public DeleteNotExistsExecutor(Connection connection, String sql, int line, File scriptFile, Properties globalProperties)
|
||||
{
|
||||
this(connection, sql, line, scriptFile, globalProperties, null);
|
||||
}
|
||||
|
||||
public DeleteNotExistsExecutor(Connection connection, String sql, int line, File scriptFile, Properties globalProperties, Dialect dialect)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.sql = sql;
|
||||
this.line = line;
|
||||
this.scriptFile = scriptFile;
|
||||
this.globalProperties = globalProperties;
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
||||
public void checkProperties()
|
||||
@@ -164,6 +173,21 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Integer.MIN_VALUE in case of MySQL otherwise the batch size.
|
||||
*/
|
||||
private int computeFetchSize()
|
||||
{
|
||||
if (this.dialect instanceof MySQLInnoDBDialect)
|
||||
{
|
||||
// Note the MySQL specific fetch size limitation (Integer.MIN_VALUE). fetchSize
|
||||
// activates result set streaming.
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
private void process(Pair<String, String>[] tableColumn, Long[] tableUpperLimits, String[] optionalWhereClauses) throws SQLException
|
||||
{
|
||||
// The approach is to fetch ordered row ids from all referencer/secondary (e.g.
|
||||
@@ -184,6 +208,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
PreparedStatement[] secondaryPrepStmts = null;
|
||||
PreparedStatement deletePrepStmt = null;
|
||||
Set<Long> deleteIds = new HashSet<>();
|
||||
int fetchSize = computeFetchSize();
|
||||
|
||||
deletedCount = 0L;
|
||||
startTime = new Date();
|
||||
@@ -191,7 +216,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
{
|
||||
connection.setAutoCommit(false);
|
||||
primaryPrepStmt = connection.prepareStatement(createPreparedSelectStatement(primaryTableName, primaryColumnName, primaryWhereClause));
|
||||
primaryPrepStmt.setFetchSize(batchSize);
|
||||
primaryPrepStmt.setFetchSize(fetchSize);
|
||||
primaryPrepStmt.setLong(1, primaryId);
|
||||
primaryPrepStmt.setLong(2, tableUpperLimits[0]);
|
||||
|
||||
@@ -204,7 +229,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
for (int i = 1; i < tableColumn.length; i++)
|
||||
{
|
||||
PreparedStatement secStmt = connection.prepareStatement(createPreparedSelectStatement(tableColumn[i].getFirst(), tableColumn[i].getSecond(), optionalWhereClauses[i]));
|
||||
secStmt.setFetchSize(batchSize);
|
||||
secStmt.setFetchSize(fetchSize);
|
||||
secStmt.setLong(1, primaryId);
|
||||
secStmt.setLong(2, tableUpperLimits[i]);
|
||||
|
||||
|
@@ -350,7 +350,7 @@ public class ScriptExecutorImpl implements ScriptExecutor
|
||||
}
|
||||
else if (sql.startsWith("--DELETE_NOT_EXISTS"))
|
||||
{
|
||||
DeleteNotExistsExecutor deleteNotExists = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, globalProperties);
|
||||
DeleteNotExistsExecutor deleteNotExists = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, globalProperties, dialect);
|
||||
deleteNotExists.execute();
|
||||
|
||||
// Reset
|
||||
|
@@ -90,7 +90,7 @@ public class DeleteNotExistsExecutorTest
|
||||
{
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("true");
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_TIMEOUT_SECONDS)).thenReturn("-1");
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties, null);
|
||||
deleteNotExistsExecutor.execute();
|
||||
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
@@ -100,7 +100,7 @@ public class DeleteNotExistsExecutorTest
|
||||
{
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("false");
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_TIMEOUT_SECONDS)).thenReturn("-1");
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties, null);
|
||||
deleteNotExistsExecutor.execute();
|
||||
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
@@ -133,7 +133,7 @@ public class DeleteNotExistsExecutorTest
|
||||
{
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_DELETE_BATCH_SIZE)).thenReturn("1");
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("false");
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties, null);
|
||||
deleteNotExistsExecutor.execute();
|
||||
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
@@ -167,7 +167,7 @@ public class DeleteNotExistsExecutorTest
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_BATCH_SIZE)).thenReturn("2");
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_READ_ONLY)).thenReturn("false");
|
||||
when(properties.getProperty(DeleteNotExistsExecutor.PROPERTY_TIMEOUT_SECONDS)).thenReturn("-1");
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties);
|
||||
DeleteNotExistsExecutor deleteNotExistsExecutor = new DeleteNotExistsExecutor(connection, sql, line, scriptFile, properties, null);
|
||||
deleteNotExistsExecutor.execute();
|
||||
|
||||
List<String> res = jdbcTmpl.queryForList(select, String.class);
|
||||
|
Reference in New Issue
Block a user