This is an automated email from the ASF dual-hosted git repository.
DaanHoogland pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 21e4475d961 Optimize the DB updates to use bulk UPDATE instead of
row-level locks. (#13349)
21e4475d961 is described below
commit 21e4475d961a4cf645ccf043158f6d2bb7655a61
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Tue Jun 23 20:11:19 2026 +0530
Optimize the DB updates to use bulk UPDATE instead of row-level locks.
(#13349)
Co-authored-by: Aaron Chung <[email protected]>
---
.../java/com/cloud/alert/dao/AlertDaoImpl.java | 28 +++++++---------
.../java/com/cloud/event/dao/EventDaoImpl.java | 29 ++++++++++------
.../main/java/com/cloud/host/dao/HostDaoImpl.java | 22 +++++++-----
.../security/dao/SecurityGroupWorkDaoImpl.java | 39 +++++-----------------
4 files changed, 53 insertions(+), 65 deletions(-)
diff --git a/engine/schema/src/main/java/com/cloud/alert/dao/AlertDaoImpl.java
b/engine/schema/src/main/java/com/cloud/alert/dao/AlertDaoImpl.java
index 94d01f472ba..97b7c54f084 100644
--- a/engine/schema/src/main/java/com/cloud/alert/dao/AlertDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/alert/dao/AlertDaoImpl.java
@@ -20,6 +20,7 @@ import java.util.Date;
import java.util.List;
+import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import com.cloud.alert.AlertVO;
@@ -28,7 +29,7 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.UpdateBuilder;
@Component
public class AlertDaoImpl extends GenericDaoBase<AlertVO, Long> implements
AlertDao {
@@ -107,25 +108,20 @@ public class AlertDaoImpl extends GenericDaoBase<AlertVO,
Long> implements Alert
}
sc.setParameters("archived", false);
- boolean result = true;
- ;
List<AlertVO> alerts = listBy(sc);
if (ids != null && alerts.size() < ids.size()) {
- result = false;
- return result;
+ return false;
}
- if (alerts != null && !alerts.isEmpty()) {
- TransactionLegacy txn = TransactionLegacy.currentTxn();
- txn.start();
- for (AlertVO alert : alerts) {
- alert = lockRow(alert.getId(), true);
- alert.setArchived(true);
- update(alert.getId(), alert);
- txn.commit();
- }
- txn.close();
+
+ if (CollectionUtils.isEmpty(alerts)) {
+ return true;
}
- return result;
+
+ AlertVO alertForUpdate = createForUpdate();
+ alertForUpdate.setArchived(true);
+ UpdateBuilder ub = getUpdateBuilder(alertForUpdate);
+ update(ub, sc, null);
+ return true;
}
@Override
diff --git a/engine/schema/src/main/java/com/cloud/event/dao/EventDaoImpl.java
b/engine/schema/src/main/java/com/cloud/event/dao/EventDaoImpl.java
index e748e98900e..9417ddd1259 100644
--- a/engine/schema/src/main/java/com/cloud/event/dao/EventDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/event/dao/EventDaoImpl.java
@@ -18,8 +18,10 @@ package com.cloud.event.dao;
import java.util.Date;
import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import com.cloud.event.Event.State;
@@ -29,12 +31,13 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.UpdateBuilder;
@Component
public class EventDaoImpl extends GenericDaoBase<EventVO, Long> implements
EventDao {
protected final SearchBuilder<EventVO> CompletedEventSearch;
protected final SearchBuilder<EventVO> ToArchiveOrDeleteEventSearch;
+ protected final SearchBuilder<EventVO> ArchiveByIdsSearch;
public EventDaoImpl() {
CompletedEventSearch = createSearchBuilder();
@@ -51,6 +54,10 @@ public class EventDaoImpl extends GenericDaoBase<EventVO,
Long> implements Event
ToArchiveOrDeleteEventSearch.and("createdDateL",
ToArchiveOrDeleteEventSearch.entity().getCreateDate(), Op.LTEQ);
ToArchiveOrDeleteEventSearch.and("archived",
ToArchiveOrDeleteEventSearch.entity().getArchived(), Op.EQ);
ToArchiveOrDeleteEventSearch.done();
+
+ ArchiveByIdsSearch = createSearchBuilder();
+ ArchiveByIdsSearch.and("id", ArchiveByIdsSearch.entity().getId(),
Op.IN);
+ ArchiveByIdsSearch.done();
}
@Override
@@ -100,16 +107,16 @@ public class EventDaoImpl extends GenericDaoBase<EventVO,
Long> implements Event
@Override
public void archiveEvents(List<EventVO> events) {
- if (events != null && !events.isEmpty()) {
- TransactionLegacy txn = TransactionLegacy.currentTxn();
- txn.start();
- for (EventVO event : events) {
- event = lockRow(event.getId(), true);
- event.setArchived(true);
- update(event.getId(), event);
- txn.commit();
- }
- txn.close();
+ if (CollectionUtils.isEmpty(events)) {
+ return;
}
+
+ List<Long> ids =
events.stream().map(EventVO::getId).collect(Collectors.toList());
+ SearchCriteria<EventVO> sc = ArchiveByIdsSearch.create();
+ sc.setParameters("id", ids.toArray(new Object[ids.size()]));
+ EventVO eventForUpdate = createForUpdate();
+ eventForUpdate.setArchived(true);
+ UpdateBuilder ub = getUpdateBuilder(eventForUpdate);
+ update(ub, sc, null);
}
}
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
index cd4423dfa26..5b8a38b8e5b 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
@@ -646,16 +646,22 @@ public class HostDaoImpl extends GenericDaoBase<HostVO,
Long> implements HostDao
sc.setParameters("lastPinged", lastPingSecondsAfter);
sc.setParameters("status", Status.Disconnected, Status.Down,
Status.Alert);
- StringBuilder sb = new StringBuilder();
- List<HostVO> hosts = lockRows(sc, null, true); // exclusive lock
- for (HostVO host : hosts) {
- host.setManagementServerId(null);
- update(host.getId(), host);
- sb.append(host.getId());
- sb.append(" ");
+ // SELECT before bulk UPDATE to preserve per-host-ID trace logging —
the bulk UPDATE
+ // cannot return which rows it matched since the WHERE column is being
set to NULL
+ if (logger.isTraceEnabled()) {
+ List<HostVO> hosts = listBy(sc);
+ StringBuilder sb = new StringBuilder();
+ for (HostVO host : hosts) {
+ sb.append(host.getId());
+ sb.append(" ");
+ }
+ logger.trace("Following hosts will be reset: {}", sb);
}
- logger.trace("Following hosts got reset: {}", sb);
+ HostVO host = createForUpdate();
+ host.setManagementServerId(null);
+ UpdateBuilder ub = getUpdateBuilder(host);
+ update(ub, sc, null);
}
/*
diff --git
a/engine/schema/src/main/java/com/cloud/network/security/dao/SecurityGroupWorkDaoImpl.java
b/engine/schema/src/main/java/com/cloud/network/security/dao/SecurityGroupWorkDaoImpl.java
index 327d12c759a..3180ef30a3c 100644
---
a/engine/schema/src/main/java/com/cloud/network/security/dao/SecurityGroupWorkDaoImpl.java
+++
b/engine/schema/src/main/java/com/cloud/network/security/dao/SecurityGroupWorkDaoImpl.java
@@ -116,7 +116,7 @@ public class SecurityGroupWorkDaoImpl extends
GenericDaoBase<SecurityGroupWorkVO
//ensure that there is no job in Processing state for the same
VM
processing = true;
if (logger.isTraceEnabled()) {
- logger.trace("Security Group work take: found a job in
Scheduled and Processing vmid=" + work.getInstanceId());
+ logger.trace("Security Group work take: found a job in
Scheduled and Processing vmid={}", work.getInstanceId());
}
}
work.setServerId(serverId);
@@ -141,26 +141,16 @@ public class SecurityGroupWorkDaoImpl extends
GenericDaoBase<SecurityGroupWorkVO
}
@Override
- @DB
public void updateStep(Long vmId, Long logSequenceNumber, Step step) {
- final TransactionLegacy txn = TransactionLegacy.currentTxn();
- txn.start();
SearchCriteria<SecurityGroupWorkVO> sc = VmIdSeqNumSearch.create();
sc.setParameters("vmId", vmId);
sc.setParameters("seqno", logSequenceNumber);
- final Filter filter = new Filter(SecurityGroupWorkVO.class, null,
true, 0l, 1l);
-
- final List<SecurityGroupWorkVO> vos = lockRows(sc, filter, true);
- if (vos.size() == 0) {
- txn.commit();
- return;
- }
- SecurityGroupWorkVO work = vos.get(0);
- work.setStep(step);
- update(work.getId(), work);
-
- txn.commit();
+ SecurityGroupWorkVO workForUpdate = createForUpdate();
+ workForUpdate.setStep(step);
+ // LIMIT 1 preserves the original single-row semantics: op_nwgrp_work
has no
+ // uniqueness on (instance_id, seq_no), so without it duplicate rows
would all be updated.
+ update(workForUpdate, sc, 1);
}
@Override
@@ -172,21 +162,10 @@ public class SecurityGroupWorkDaoImpl extends
GenericDaoBase<SecurityGroupWorkVO
}
@Override
- @DB
public void updateStep(Long workId, Step step) {
- final TransactionLegacy txn = TransactionLegacy.currentTxn();
- txn.start();
-
- SecurityGroupWorkVO work = lockRow(workId, true);
- if (work == null) {
- txn.commit();
- return;
- }
- work.setStep(step);
- update(work.getId(), work);
-
- txn.commit();
-
+ SecurityGroupWorkVO workForUpdate = createForUpdate();
+ workForUpdate.setStep(step);
+ update(workId, workForUpdate);
}
@Override