Ran
Ran

Reputation: 662

Transactions fails due to "Lock wait timeout exceeded; try restarting transaction"

When trying to update a certain table, it fails with the exception of: "Lock wait timeout exceeded; try restarting transaction". Some info: I have two tables, profile and profile_units. ID is the primary key of the profile table, and ID is part of a primary key in profile_units, and is also a foreign key to ID in profile. Whan I call saveProfileChanges, the updateAllFields method succeeds, but the addStmt.executeUpdate(); in handleActivityUnitsChanges fails with the above exception. I use MySQL v5.0 for a data base. What am I doing wrong?

I try to execute the following code:

    public static Profile saveProfileChanges(Profile profile, List unitsToAdd)
        throws Exception
{
    Connection con = null;
    try
    {
        con = ConnectionManager.getConnection();

        updateAllFields(con, profile);

        handleActivityUnitsChanges(con, profile, unitsToAdd);

        con.commit();
        return profile;
    }
    finally
    {
        ConnectionManager.closeConnection(con);
    }
}

private static void handleActivityUnitsChanges(Connection con, Profile profile, List<ActivityUnit> unitsToAdd) throws Exception
{
    PreparedStatement addStmt = null;

    try
    {
        for (ActivityUnit currentUnitToAdd : unitsToAdd)
        {
            String sqlStatement = "insert into profile_units (ID, ActivityUnit) values (?, ?)";
            addStmt = con.prepareStatement(sqlStatement);

            addStmt.setLong(1, profile.getId());
            addStmt.setLong(2, currentUnitToAdd.getId());

            System.out.println(sqlStatement);

            addStmt.executeUpdate();
            addStmt.close();
        }
    }
    catch (Exception e)
    {
        con.rollback();
        throw e;
    }
    finally
    {
        ConnectionManager.closeStatement(addStmt);
    }
}

public static Connection getConnection() throws Exception
{
    Class.forName("com.mysql.jdbc.Driver").newInstance();
    Connection con = DriverManager.getConnection("jdbc:mysql:///someproject", "a", "a");

    con.setAutoCommit(false);

    return con;
}

Upvotes: 0

Views: 5336

Answers (2)

Ran
Ran

Reputation: 662

OK, I figured out what the problem was - In updateAllFields (which for some odd reason i didn't showed here) I obtained a new connection, so the two transactions got mixed. Thanks for the help anyone!

Upvotes: 3

Devart
Devart

Reputation: 121902

Take a look at innodb_lock_wait_timeout variable. It is - the timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. The default value is 50 seconds, you could increase this value; but I think is better to rewrite loop-inserts code or to optimize something.

As a variant - try to run less insert statements in transaction. To speed up transaction you could use multiple inserts, e.g. - 'INSERT INTO table1(column1, column2) VALUES(1,'text1'),(2,'text2')...;'

Upvotes: 0

Related Questions