CS-12510: Deleting the host_details and inserting them back causes deadlocks.

Reviewed-By: Alex

Changes:
- Deleting and inserting the host_details in one transaction leads to this MySQL deadlock issue sometimes
- This fix is to use the ON DUPLICATE KEY UPDATE MySQL query that will insert the deatils if they are new or update the ones that are existing.
- This needs a UNIQUE constraint on host_details.
This commit is contained in:
prachi 2012-08-01 14:29:38 -07:00
parent 721a85f1b5
commit c55489224b
3 changed files with 22 additions and 10 deletions

View File

@ -12,6 +12,8 @@
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.host.dao;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -24,6 +26,7 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value=HostDetailsDao.class)
public class HostDetailsDaoImpl extends GenericDaoBase<DetailVO, Long> implements HostDetailsDao {
@ -84,19 +87,26 @@ public class HostDetailsDaoImpl extends GenericDaoBase<DetailVO, Long> implement
@Override
public void persist(long hostId, Map<String, String> details) {
final String InsertOrUpdateSql = "INSERT INTO `cloud`.`host_details` (host_id, name, value) VALUES (?,?,?) ON DUPLICATE KEY UPDATE value=?";
Transaction txn = Transaction.currentTxn();
txn.start();
SearchCriteria<DetailVO> sc = HostSearch.create();
sc.setParameters("hostId", hostId);
expunge(sc);
for (Map.Entry<String, String> detail : details.entrySet()) {
String value = detail.getValue();
if("password".equals(detail.getKey())){
value = DBEncryptionUtil.encrypt(value);
}
DetailVO vo = new DetailVO(hostId, detail.getKey(), value);
persist(vo);
String value = detail.getValue();
if("password".equals(detail.getKey())){
value = DBEncryptionUtil.encrypt(value);
}
try {
PreparedStatement pstmt = txn.prepareAutoCloseStatement(InsertOrUpdateSql);
pstmt.setLong(1, hostId);
pstmt.setString(2, detail.getKey());
pstmt.setString(3, value);
pstmt.setString(4, value);
pstmt.executeUpdate();
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to persist the host_details key: "+ detail.getKey() +" for host id: "+hostId, e);
}
}
txn.commit();
}

View File

@ -832,7 +832,8 @@ CREATE TABLE `cloud`.`host_details` (
`name` varchar(255) NOT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_host_details__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE
CONSTRAINT `fk_host_details__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
CONSTRAINT UNIQUE KEY (`host_id`, `name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`mshost` (

View File

@ -350,3 +350,4 @@ UPDATE `cloud`.`hypervisor_capabilities` SET `max_data_volumes_limit`=13 WHERE `
SET SQL_SAFE_UPDATES=1;
UPDATE `cloud`.`configuration` SET description='In second, timeout for creating volume from snapshot' WHERE name='create.volume.from.snapshot.wait';
ALTER TABLE `cloud`.`host_details` ADD CONSTRAINT UNIQUE KEY (`host_id`, `name`);