0

Hi I have a problem with query insiede a restore procedure after Exception. This is the code (the main part of it)

@Override
@Async
@Transactional(rollbackFor=Exception.class)
public void modifyFleet(User currentUser, FleetForm fleetForm) throws Exception {
    //Keep the progress status on DB
    fleetServices.setEditingProgress(fleetForm.getIdFleet(), "Start editing fleet");
    Fleet oldFleet = fleetServices.findById(fleetForm.getIdFleet());
    //some INSTRUCTIONS
    if (!(backupFolderFile.mkdirs()))
        throw new FileSystemException("Error making the folder backup");
    try{
        //Keep the progress status on DB
        fleetServices.setEditingProgress(fleetForm.getIdFleet(), "Backup...");
        FileUtils.copyDirectory(fleetFile, new File(backupFolder));

        //Create fleet with new value
        Fleet newFleet = newFleetConstructor(fleetForm, oldFleet);
        //Change operation for all cars of the application
        int i = 0;
        for (Car car:oldFleet.getCars()){
            //some INSTRUCTIONS

            //Keep the progress status on DB
            fleetServices.setEditingProgress(fleetForm.getIdFleet(), "Work on car "+ car.getCarType().getIdCarType() + car.getId()+ " (" + i +" of " + oldFleet.getCars().size() +"): Editing acquisitions file"  );

        }

        fleetServices.setEditingProgress(oldFleet.getIdFleet(), "Updating file system fleet path");
        utils.unSetEditingFleet(oldFleet.getIdFleet());
//          throw new Exception("fleet has been restored Exception");
    }catch(Exception e){
        //Keep the progress status on DB
        fleetServices.setEditingProgress(oldFleet.getIdFleet(), "Sorry an error occured during the procedure, wait until restore is ended!");
        //Restore the file system procedure
        restoreProcedure(oldFleet.getIdFleet(), fleetFile, backupFolderFile);       
        //Keep the progress status on DB
        fleetServices.setEditingProgress(oldFleet.getIdFleet(), "");
        utils.unSetEditingFleet(oldFleet.getIdFleet());
        //Even with this exception set the fleet as not in editing
        throw new EditingException("fleet has been restored!");
    }
}

To try what happen when excepton occures during unSetEditingFleet I throw a new exception :

@Transactional
public void unSetEditingFleet(Integer idFleet) throws QueryException {
    try {
        fleetServices.setEditingFleet(idFleet, false);  
        throw new Exception();
//          for(Car car : carServices.findByFleetIdFleet(idFleet)){
//              carServices.setEditingCar(car.getIdCar(), false);   //Unset cars associated with the fleet 
//          }    
    }catch(Exception e){
        throw new QueryException(e);
    }
}

The instruction fleetServices.setEditingProgress after the Exception catch generates the exception:

Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3847)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3783)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2447)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2594)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1901)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2113)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2049)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2034)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
    ... 54 more 

the code of setEditinProgress is the following:

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW) //necessary to set immediately the text into the database inside a transactional method. This annotation create a new transaction
public void setEditingProgress(Integer idFleet, String editingProgress) {
    fleetRepository.setEditingProgress(idFleet, editingProgress);   
}

This set into database the progress status of the operation so the user can know the progress status. Why only after the catch I receive this exception? Do you know how can I fix it?

luca
  • 3,248
  • 10
  • 66
  • 145

1 Answers1

0

From what I've found out I can tell that your transaction on the database times out because another thread keeps a record lock on some record for too long. Check which other threads do operations on that table at the same time. There are different ways to figure out what blocks the transaction as shown here

if your running a busy db use:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

then:

SET innodb_lock_wait_timeout = 5000; 

works as a workaround but your queries need to be optimized.

David Fischer
  • 75
  • 1
  • 6