avoid mysql lock-promotion situation.

This commit is contained in:
Kelven Yang 2014-03-15 12:56:19 -07:00
parent 0c1b6b44a8
commit de252adadf
2 changed files with 34 additions and 30 deletions

View File

@ -899,7 +899,8 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
@Override @Override
public boolean updateState(Status oldStatus, Event event, Status newStatus, Host vo, Object data) { public boolean updateState(Status oldStatus, Event event, Status newStatus, Host vo, Object data) {
HostVO host = findById(vo.getId()); // lock target row from beginning to avoid lock-promotion caused deadlock
HostVO host = lockRow(vo.getId(), true);
if (host == null) { if (host == null) {
if (event == Event.Remove && newStatus == Status.Removed) { if (event == Event.Remove && newStatus == Status.Removed) {
host = findByIdIncludingRemoved(vo.getId()); host = findByIdIncludingRemoved(vo.getId());

View File

@ -417,41 +417,44 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
@Override @Override
public boolean updateState(State oldState, Event event, State newState, VirtualMachine vm, Object opaque) { public boolean updateState(State oldState, Event event, State newState, VirtualMachine vm, Object opaque) {
if (newState == null) { if (newState == null) {
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("There's no way to transition from old state: " + oldState.toString() + " event: " + event.toString()); s_logger.debug("There's no way to transition from old state: " + oldState.toString() + " event: " + event.toString());
} }
return false; return false;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Pair<Long, Long> hosts = (Pair<Long, Long>)opaque; Pair<Long, Long> hosts = (Pair<Long,Long>)opaque;
Long newHostId = hosts.second(); Long newHostId = hosts.second();
VMInstanceVO vmi = (VMInstanceVO)vm; VMInstanceVO vmi = (VMInstanceVO)vm;
Long oldHostId = vmi.getHostId(); Long oldHostId = vmi.getHostId();
Long oldUpdated = vmi.getUpdated(); Long oldUpdated = vmi.getUpdated();
Date oldUpdateDate = vmi.getUpdateTime(); Date oldUpdateDate = vmi.getUpdateTime();
if (newState.equals(oldState) && newHostId != null && newHostId.equals(oldHostId)) { if ( newState.equals(oldState) && newHostId != null && newHostId.equals(oldHostId) ) {
// state is same, don't need to update // state is same, don't need to update
return true; return true;
} }
SearchCriteria<VMInstanceVO> sc = StateChangeSearch.create(); // lock the target row at beginning to avoid lock-promotion caused deadlock
sc.setParameters("id", vmi.getId()); lockRow(vm.getId(), true);
sc.setParameters("states", oldState);
sc.setParameters("host", vmi.getHostId()); SearchCriteria<VMInstanceVO> sc = StateChangeSearch.create();
sc.setParameters("update", vmi.getUpdated()); sc.setParameters("id", vmi.getId());
sc.setParameters("states", oldState);
sc.setParameters("host", vmi.getHostId());
sc.setParameters("update", vmi.getUpdated());
vmi.incrUpdated(); vmi.incrUpdated();
UpdateBuilder ub = getUpdateBuilder(vmi); UpdateBuilder ub = getUpdateBuilder(vmi);
ub.set(vmi, "state", newState); ub.set(vmi, "state", newState);
ub.set(vmi, "hostId", newHostId); ub.set(vmi, "hostId", newHostId);
ub.set(vmi, "podIdToDeployIn", vmi.getPodIdToDeployIn()); ub.set(vmi, "podIdToDeployIn", vmi.getPodIdToDeployIn());
ub.set(vmi, _updateTimeAttr, new Date()); ub.set(vmi, _updateTimeAttr, new Date());
int result = update(vmi, sc); int result = update(vmi, sc);
if (result == 0) { if (result == 0) {
VMInstanceVO vo = findByIdIncludingRemoved(vm.getId()); VMInstanceVO vo = findByIdIncludingRemoved(vm.getId());