执行 XA 事务时 DB2 死锁问题 SQLCODE=-911, SQLERRMC=68

Posted

技术标签:

【中文标题】执行 XA 事务时 DB2 死锁问题 SQLCODE=-911, SQLERRMC=68【英文标题】:DB2 deadlock issue SQLCODE=-911, SQLERRMC=68 while performing XA transaction 【发布时间】:2012-03-19 18:10:34 【问题描述】:

我正在编写一个示例 jdbc 代码,它试图实现两阶段提交。有 2 个数据源,都符合 DB2 和 XA。创建了 2 个单独的 jdbc 连接。我正在使用 Atomikos 作为 TM。使用这些连接,对数据源进行更新。但是,更新查询未执行并返回 -911 错误。我无法弄清楚死锁发生的原因和位置。另外,两个连接都是独立的,不相关的,为什么会出现死锁/超时?

....   
     try

        //Get the datasource connection using jndi custom class

        JndiConn jcon1 = new JndiConn("jdbc/myDatasource1");
        JndiConn jcon2 = new JndiConn("jdbc/myDatasource2");
        UserTransactionImpl utx = new UserTransactionImpl();
        try
            //Begin transaction             
            utx.begin();

            //Get the connection from the DB
            conn1 = jcon1.ds.getConnection();
            conn2 = jcon2.ds.getConnection();

            //Reading the data from the form
            int frmAccntNum = Integer.parseInt(req.getParameter("frmAccnt"));
            int toAccntNum = Integer.parseInt(req.getParameter("toAccnt"));
            int amt = Integer.parseInt(req.getParameter("amt"));

            //Create a statement from the Connection

            try
                String selectQuery = "select AccountNumber, Balance from Accounts where AccountNumber =? with ur";
                PreparedStatement stmt = conn1.prepareStatement(selectQuery);
                stmt.setInt(1,frmAccntNum);
                ResultSet rs = stmt.executeQuery();
                rs.next();
                Account frmAccnt = new Account(rs.getInt(1),rs.getInt(2));
                int tempBal = frmAccnt.getBalance();

                PreparedStatement stmt2 = conn2.prepareStatement(selectQuery);
                stmt2.setInt(1, toAccntNum);
                ResultSet rs1 = stmt.executeQuery();
                rs1.next();
                Account toAccnt = new Account(rs1.getInt(1),rs1.getInt(2));
                int tempBal2 = toAccnt.getBalance();

                
                Operations t1 = new Operations();
                if(t1.checkAmt(frmAccnt,amt))
                    t1.Withdraw(frmAccnt, amt);
                    t1.Deposit(toAccnt, amt);
                


                String updateQuery = "update Accounts set Balance = ? where AccountNumber= ? with ur";
                stmt = conn1.prepareStatement(updateQuery);
                stmt.setInt(1, frmAccnt.getBalance());
                stmt.setInt(2,frmAccnt.getAccountNumber());
                stmt.executeUpdate();

                stmt2 = conn2.prepareStatement(updateQuery);
                stmt2.setInt(1, toAccnt.getBalance());
                stmt2.setInt(2,toAccnt.getAccountNumber());
                stmt2.executeUpdate();
                //int r1 = stmt.executeUpdate("update Accounts set Balance = "+frmAccnt.getBalance()+"where AccountNumber="+frmAccnt.getAccountNumber());

                stmt.close();
                stmt2.close();

            catch(SQLException sq)
                System.out.println("Setting Rollback true");
                sq.printStackTrace();
                rollback = true;
            
        catch(Exception ex)
            ex.printStackTrace();
        finally
            if(!rollback)
                try
                    utx.commit();
                catch(Exception e)
                    System.out.println("Commit Exception");
                    e.printStackTrace();
                    rollback = true;
                    try 
                        utx.rollback();
                     catch (Exception e1) 
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                     
                
            
            else
                try 
                    utx.rollback();
                 catch (Exception e2) 
                    // TODO Auto-generated catch block
                    e2.printStackTrace();
                 
            
            try 
                conn1.close();
                conn2.close();
             catch (SQLException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            

           
    catch(NamingException nme)
        nme.printStackTrace();
    

【问题讨论】:

在打开 rs1 之前尝试关闭 rs(我认为是 rs.close()),并在发出更新语句之前关闭 rs1。这有帮助吗?听起来好像没有关闭。 我试过关闭rs和rs1,结果还是死锁。 【参考方案1】:

因为这样:

ResultSet rs1 = stmt.executeQuery();

你想要的

ResultSet rs1 = stmt2.executeQuery();

【讨论】:

啊...是的..tht 解决了它。天哪,错过了这么愚蠢的事情:(谢谢!!

以上是关于执行 XA 事务时 DB2 死锁问题 SQLCODE=-911, SQLERRMC=68的主要内容,如果未能解决你的问题,请参考以下文章

6 张图带你彻底搞懂分布式事务 XA 模式

详解Mysql分布式事务XA(跨数据库事务)

db2 V9.1 死锁

分布式事物之 xa协议两阶段提交

当MySQL执行XA事务时遭遇崩溃,且看华为云如何保障数据一致性

SQL0911N 由于死锁或超时,已回滚当前事务。原因码“68”。SQLSTATE=40001