【问题标题】:Java and MySQL TransactionsJava 和 MySQL 事务
【发布时间】:2012-05-11 01:27:43
【问题描述】:

我有一个在多台计算机上运行的 java 应用程序,它们都连接到同一个 MySQL 数据库。我需要事务以确保正确更新数据库。

我在释放锁时遇到问题。代码如下:

public boolean bookSeats(int numeroSala, Calendar dataOra, List<Posto> posti) {
    JDBConnection connection = JDBConnection.getDbConnection();
    Connection conn = connection.conn;
    java.sql.Date javaSqlDate = new java.sql.Date(dataOra.getTime().getTime());
    java.sql.Time javaSqlTime = new java.sql.Time(dataOra.getTime().getTime());

    try {
        conn.setAutoCommit(false);
        conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
    } catch (SQLException e) {
        e.printStackTrace();
    }

    try
    {
        Posto p = null;
        ListIterator<Posto> itr = posti.listIterator();
        PreparedStatement stmt = null;
        stmt = conn.prepareStatement(
            "INSERT INTO sala?_tickets " + 
            "(giornoSpettacolo, orarioSpettacolo, fila, posto) " + 
            "VALUES (?, ?, ?, ?)");

        stmt.setInt(1, numeroSala);
        while(itr.hasNext())
        {
            p = itr.next();
            stmt.setString(2, javaSqlDate.toString()); // giornoSpettacolo
            stmt.setString(3, javaSqlTime.toString()); // orarioSpettacolo
            stmt.setInt(4, p.getFila()); // fila
            stmt.setInt(5, p.getNumero()); // posto
            stmt.addBatch();
        }

        stmt.executeBatch();

        conn.commit();
        return true;
    }
    catch (SQLException e) {
        e.printStackTrace();
    }

    return false;
}

此方法工作正常,但当我尝试同时在另一台计算机上执行此方法时,即使 conn.commit() 已完成,我也会收到 DEADLOCK 错误。

只要我关闭第一个应用程序,另一个应用程序就可以运行该方法而不会出现死锁错误。 COMMIT 好像没有释放锁?

【问题讨论】:

    标签: java mysql jdbc transactions


    【解决方案1】:

    根据 MySQL 文档,关于 SERIALIZABLE:

    这个级别类似于 REPEATABLE READ,但 InnoDB 隐式转换所有 普通的 SELECT 语句到 SELECT ... LOCK IN SHARE MODE 如果自动提交 已禁用。

    您可能想在提交后尝试重新启用自动提交,或尝试连接。改为 REPEATABLE_READ。

    【讨论】:

    • 谢谢,这解决了我的问题!
    【解决方案2】:

    您可以参考this documentantion 了解如何使用裸 JDBC 进行事务。希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      您应该始终在finally 块中执行conn.close(),以确保释放您的方法使用的任何资源。

      【讨论】:

        【解决方案4】:

        是的,按照第一个答案的说明关闭连接。但是,另外,如果你能把上面的代码放到一个“同步”的方法中,就可以保证一次只有一个线程可以访问它。

        除此之外,看看下面的链接,它讨论了 JDBC 中的死锁处理

        Deadlock detection in Java

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-14
          • 1970-01-01
          • 2012-10-28
          • 2015-04-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-22
          相关资源
          最近更新 更多