</update>
<delete id="deleteByProjectUuidExcludingMarker" parameterType="map">
+ <include refid="sql_deleteByProjectUuidExcludingMarker"/>
+ </delete>
+
+ <!--
+ best practice on MySQL : order the rows to be locked in order
+ to minimze risk of deadlock.
+ https://stackoverflow.com/a/2423921/229031
+ https://jira.sonarsource.com/browse/SONAR-10117?focusedCommentId=153555&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-153555
+ -->
+ <delete id="deleteByProjectUuidExcludingMarker" parameterType="map" databaseId="mysql">
+ <include refid="sql_deleteByProjectUuidExcludingMarker"/>
+ order by uuid
+ </delete>
+
+ <sql id="sql_deleteByProjectUuidExcludingMarker">
delete from live_measures
where
project_uuid = #{projectUuid, jdbcType=VARCHAR} and
(update_marker != #{marker, jdbcType=VARCHAR} or update_marker is null)
- </delete>
+ </sql>
<select id="selectTreeByQuery" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
select <include refid="columns"/> from live_measures lm
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.measure.LiveMeasureDao;
+import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
@Override
public void visitAny(Component component) {
+ int count = 0;
LiveMeasureDao dao = dbClient.liveMeasureDao();
Multimap<String, Measure> measures = measureRepository.getRawMeasures(component);
for (Map.Entry<String, Collection<Measure>> measuresByMetricKey : measures.asMap().entrySet()) {
}
Metric metric = metricRepository.getByKey(metricKey);
Predicate<Measure> notBestValueOptimized = BestValueOptimization.from(metric, component).negate();
- measuresByMetricKey.getValue().stream()
+ Iterator<LiveMeasureDto> liveMeasures = measuresByMetricKey.getValue().stream()
.filter(NonEmptyMeasure.INSTANCE)
.filter(notBestValueOptimized)
.map(measure -> measureToMeasureDto.toLiveMeasureDto(measure, metric, component))
- .forEach(dto -> dao.insertOrUpdate(dbSession, dto, marker));
+ .iterator();
+ while (liveMeasures.hasNext()) {
+ dao.insertOrUpdate(dbSession, liveMeasures.next(), marker);
+ count++;
+ if (count % 100 == 0) {
+ // use short transactions to avoid potential deadlocks on MySQL
+ // https://jira.sonarsource.com/browse/SONAR-10117?focusedCommentId=153555&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-153555
+ dbSession.commit();
+ }
+ }
}
}
}