Timeout updating DB2 table

11,800

Solution 1

Sorry to answer my own question, but I found out the problem. This is a somewhat homemade framework where a DAO keeps track of it's own connection.

conn = getConn();

This will return the same connection for each DAO method while in an explicit transaction.

While I was stepping through the code, I found out that a method I was calling in my transaction was creating a new transaction, a new DAO, and therefore a new DB connection. So now I have 2 transactions open and 2 connections. It's easy to see at this point, that I am in fact deadlocking myself.

This caught me a little by surprise since the previous app I worked on allowed nested transactions. (Using the same DB connection for both transactions)

Solution 2

So SQL connections will timeout, you will need to specify to the connection that you want to "test" the connection before executing a query so that it can then reconnect if it's not still open.

I only have code for the apache commons DBCP and pooling, but here is what I do with my own connections. The important lines are connectionPool.setTestOnBorrow(true); and specifying the validation query factory.setValidationQuery("select 1");

GenericObjectPool connectionPool = new GenericObjectPool(null);
...
connectionPool.setTestOnBorrow(true); // test the connection before its made
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI,username, password);

final String validationQuery = null;
KeyedObjectPoolFactory statementPool = new GenericKeyedObjectPoolFactory(null);
PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory, connectionPool,
        statementPool, validationQuery, defaultReadOnly, defaultAutoCommit);

factory.setValidationQuery("select 1");    // validate the connection with this statement
Share:
11,800
Jess
Author by

Jess

Hi, my name is Jess, I am an experienced software and app developer. I cut my teeth as a young dev writing logistics software in INFORMIX 4GL and later C++ and ASP.NET. I had a stint at IBM chip manufacturing developing in perl and node.js. Now I am writing web apps for energy efficiency in ASP.NET Core, EF, Bootstrap and various JS technologies. Faves: C#, ASP.NET, Bootstrap, Javascript, SQL, visual studio, git.

Updated on June 30, 2022

Comments

  • Jess
    Jess almost 2 years

    I am doing an update to a DB2 table like this (java code):

    // Some code  ripped out for brevity...
    sql.append("UPDATE " + TABLE_THREADS + " ");
    sql.append("SET STATUS = ? ");
    sql.append("WHERE ID = ?");
    
    conn = getConn();
    pstmt = conn.prepareStatement(sql.toString());
    int idx1 = 0;
    pstmt.setInt(++idx1, status);
    pstmt.setInt(++idx1, id);
    int rowsUpdated = pstmt.executeUpdate();
    return rowsUpdated;
    

    After a long while, I get a rollback and an error message:

    UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C9008E, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SOME.THING.X'000002'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.57.82

    The documentation for error -913 says this REASON CODE means it is a timeout. The resource type, 00000302 is a table space page, and I do not recognize the resource name at all.

    When I run the SQL by itself, it works fine:

    UPDATE MY.THREADS
    SET STATUS = 1
    WHERE ID = 156
    

    I can SELECT and see the status has been updated. (Although when I run this SQL during the long wait period before the timeout, I have the same issue. It takes forever and I just cancel it).

    There are several things happening in the transaction and I don't see any other updates to this table or record. There are create/delete triggers on the table, but no update triggers. I don't see any selects with cursors, or weird isolation level changes. I don't see much else in the transaction that would cause this.

    Why am I getting this error? What else should I look for in the transaction?


    EDIT:

    I stepped through the code from the beginning of the request to where it gets 'stuck'. It seems as if there are 2 DAO's and both of them are creating a transaction. I think that might be the problem.