Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在同一线程中打开两个JDBC事务的死锁_Java_Sql Server_Oracle_Jdbc_Hsqldb - Fatal编程技术网

Java 在同一线程中打开两个JDBC事务的死锁

Java 在同一线程中打开两个JDBC事务的死锁,java,sql-server,oracle,jdbc,hsqldb,Java,Sql Server,Oracle,Jdbc,Hsqldb,我正在通过JDBC测试一些数据库驱动程序。其中一项测试包括测试数据库的事务功能: 我打开了同一个db的两个连接(autoCommit=false) 在连接A上,我在表中插入一行而不执行提交 在连接B上,我希望还看不到那一排 在连接上,我执行提交 在连接B上,我希望看到那一排 对于Oracle 12来说是很好的,但是对于像HSQLDB、德比或SQL Server这样的其他数据库, NO< /强>:它在步骤3的中间阻塞。 我想原因可能与事务隔离参数有关,但我在创建两个连接时尝试了所有可能的值,结果总

我正在通过JDBC测试一些数据库驱动程序。其中一项测试包括测试数据库的事务功能:

  • 我打开了同一个db的两个连接(autoCommit=false)
  • 在连接A上,我在表中插入一行而不执行提交
  • 在连接B上,我希望还看不到那一排
  • 在连接上,我执行提交
  • 在连接B上,我希望看到那一排
  • <测试>对于Oracle 12来说是很好的,但是对于像HSQLDB、德比或SQL Server这样的其他数据库,<强> NO< /强>:它在步骤3的中间阻塞。

    我想原因可能与事务隔离参数有关,但我在创建两个连接时尝试了所有可能的值,结果总是一样的

    为什么它会阻塞?为什么甲骨文没有阻止

    这是我的代码:

    public class JdbcTest
    {
        @Test
        public void twoTransactionsTest()
            throws SQLException,
            IOException
        {
            String tableName="dummy01";
            // 1. I open two connections to the same db (with autoCommit=false).
            try (Connection connectionA=createConnection(); Connection connectionB=createConnection())
            {
                createTable(connectionA, tableName);
    
                // 2. On connection A, I insert one row in a table without performing a commit.
                execute(connectionA, "INSERT INTO " + tableName + " VALUES(50, 'grecia')");
    
                // 3. On connection B, I expect not to see that row yet.
                int records=queryAndCountRows(connectionB, "SELECT id FROM " + tableName + " WHERE id=50");
                assertEquals(0, records);
    
                // 4. On connection A, I perform a commit.
                connectionA.commit();
    
                // 5. On connection B, I expect to see that row.
                records=queryAndCountRows(connectionB, "SELECT * FROM " + tableName + " WHERE id=50");
                assertEquals(1, records);
                dropTable(connectionA, tableName);
            }
        }
    
        private Connection createConnection()
            throws SQLException,
            IOException
        {
            String url="jdbc:hsqldb:demo.hsqldb";
            String user="demo";
            String password="";
            Connection connection=DriverManager.getConnection(url, user, password);
            connection.setAutoCommit(false);
            return connection;
        }
    
        private int queryAndCountRows(Connection connection, String sql)
            throws SQLException
        {
            try (PreparedStatement pst=connection.prepareStatement(sql))
            {
                try (ResultSet rs=pst.executeQuery())
                {
                    int records=0;
                    while (rs.next())
                    {
                        records++;
                    }
                    return records;
                }
            }
        }
    
        private void execute(Connection connection, String sql)
            throws SQLException
        {
            try (Statement statement=connection.createStatement())
            {
                statement.execute(sql);
            }
        }
    
        private void createTable(Connection connection, String tableName)
            throws SQLException
        {
            try
            {
                execute(connection, "DROP TABLE " + tableName);
            }
            catch (SQLException e)
            {
                // If the table already exists, let's ignore this error.
            }
            execute(connection, "CREATE TABLE " + tableName + "(id NUMBER(5) NOT NULL, name VARCHAR2(100))");
        }
    
        private void dropTable(Connection connection, String tableName)
            throws SQLException
        {
            execute(connection, "DROP TABLE " + tableName);
        }
    }
    
    我的依赖项:

    <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.3.2</version>
    </dependency>
    <dependency>
      <groupId>com.oracle</groupId>
      <artifactId>ojdbc6</artifactId>
      <version>11.2.0</version>
    </dependency>
    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
      <version>6.1.0.jre8</version>
    </dependency>
    
    
    org.hsqldb
    hsqldb
    2.3.2
    com.oracle
    ojdbc6
    11.2.0
    com.microsoft.sqlserver
    mssql jdbc
    6.1.0.jre8
    

    提前感谢。

    在Oracle中,数据库读取器从不等待编写器,除非在极不寻常的情况下,您基本上可以忽略这些情况。出于所有实际目的,读者从不等待作者

    在其他数据库中,情况并非总是如此。例如,在HSQLDB中,默认锁定模式是2PL(两阶段锁定)。在该模型中,写入表会获得该表上的独占锁,从而阻止其他会话读取该表。它有更复杂的锁定模型(如MVCC),可以使用
    set DATABASE TRANSACTION CONTROL
    命令设置


    这是一个很好的例子,说明了为什么“数据库独立性”真的很难实现(就我而言,这是我从未设定的目标)。

    在Oracle中,数据库读者从不等待编写者,除非在极不寻常的情况下,您基本上可以忽略这些情况。出于所有实际目的,读者从不等待作者

    在其他数据库中,情况并非总是如此。例如,在HSQLDB中,默认锁定模式是2PL(两阶段锁定)。在该模型中,写入表会获得该表上的独占锁,从而阻止其他会话读取该表。它有更复杂的锁定模型(如MVCC),可以使用
    set DATABASE TRANSACTION CONTROL
    命令设置


    这是一个很好的例子,说明了为什么“数据库独立性”真的很难实现(就我而言,这是我从未设定的目标)。

    如果您将HSQLDB作为服务器运行并使用MVCC,您将获得预期的结果


    当您在进程中使用HSQLDB时,必须为每个连接使用单独的线程,并使用MVCC使其工作

    如果将HSQLDB作为服务器运行并使用MVCC,您将获得预期的结果


    当您在进程中使用HSQLDB时,必须为每个连接使用单独的线程,并使用MVCC使其工作

    在这些DB系统中,隔离的实施方式不同,请按照此链接了解更多信息:


    简言之,Oracle的实现方式是writer不阻止读卡器,但其他RDBMS的实现方式并非如此。

    在这些数据库系统中,隔离的实现方式不同,有关详细信息,请遵循此链接:


    简言之,Oracle实现它的方式是writer不阻止读卡器,但对于其他RDBMS则不是这样。

    您是否尝试过:hsqldb.tx=mvcc??看看这个:@erichkizmueller谢谢你的链接。这是迄今为止我找到的最好的答案。如果您将其作为答案发布,我会选择它。@LittleSanti好的,完成。您是否尝试过:hsqldb.tx=mvcc??看看这个:@erichkizmueller谢谢你的链接。这是迄今为止我找到的最好的答案。如果你把它作为答案发布,我会选择它。@LittleSanti好的,完成了。不幸的是,无论是作为服务器还是MVCC,我都无法避免死锁。无论如何,谢谢你的提示。不幸的是,作为服务器+MVCC,我都无法避免死锁。无论如何,谢谢你的提示。