Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.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 连接隔离级别_Java_Sql_Isolation Level - Fatal编程技术网

Java 连接隔离级别

Java 连接隔离级别,java,sql,isolation-level,Java,Sql,Isolation Level,我正在写一些没有给我预期结果的spike代码 我有一张桌子,基本上是几排柜台。其他表使用这些行生成应该是唯一ID的。 当我运行下面的代码时,我所期望的是第一个到达select语句的线程将获得该行或表上的锁,从而停止对唯一id值的所有读取或写入。然而,第二个线程总是在第一个线程之前完成,因为它被休眠1s,因此它们都读取相同的值并写入相同的值,所以它只增加一次,而不是我所期望的两次 我的代码是否有任何错误,或者我对隔离级别的理解是否不正确 我已经删除了锅炉板代码。标准sql。使用MySQL数据库的连

我正在写一些没有给我预期结果的spike代码

我有一张桌子,基本上是几排柜台。其他表使用这些行生成应该是唯一ID的。 当我运行下面的代码时,我所期望的是第一个到达select语句的线程将获得该行或表上的锁,从而停止对唯一id值的所有读取或写入。然而,第二个线程总是在第一个线程之前完成,因为它被休眠1s,因此它们都读取相同的值并写入相同的值,所以它只增加一次,而不是我所期望的两次

我的代码是否有任何错误,或者我对隔离级别的理解是否不正确

我已经删除了锅炉板代码。标准sql。使用MySQL数据库的连接

private void incrementValue() {

        connection
                .setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

        statement = connection.createStatement();

        System.out.println(Thread.currentThread().getName()
                + " doing select");
        resultSet = statement.executeQuery("select * from counter");
        System.out.println(Thread.currentThread().getName()
                + "after select");
        if (counter++ == 0) {
            Thread.sleep(1000);
        }
        String incrementedValue = getIncrementedValue(resultSet);

        statement.executeUpdate("update counter set counter='"
                + incrementedValue + "'");


}

private String getIncrementedValue(ResultSet resultSet) throws SQLException {
    String value = "";
    if (resultSet.next()) {
        System.out.println(Thread.currentThread().getName() + "Value was "
                + resultSet.getString(1));

        value = (new Integer(resultSet.getString(1)) + 1) + "";

    }

    return value;

}
这是从main调用的

public static void main(String[] args) {
    DatabaseExample databaseExample = new DatabaseExample();

    Runnable runnable = new Runnable() {

        @Override
        public void run() {
            DatabaseExample databaseExample = new DatabaseExample();
            databaseExample.incrementValue();
        }
    };
    new Thread(runnable).start();

    databaseExample.incrementValue();
}

即使在可串行化隔离级别中,也可以并行进行多个选择。如果要锁定select子句上的行,请使用
select。。。用于更新

参考资料:

:

如果将FOR UPDATE与使用页锁或行锁的存储引擎一起使用,则查询检查的行将被写锁定,直到当前事务结束。在共享模式下使用锁定设置共享锁定,该锁定允许其他事务读取检查的行,但不更新或删除它们

:

可序列化

此级别类似于可重复读取,但InnoDB隐式地将所有普通SELECT语句转换为SELECT。。。如果禁用自动提交,则锁定共享模式


在这种情况下,必须在应用级别进行锁定。只需使用关键字
synchronized
同步您的方法即可。请注意,这将影响应用程序性能。您可能希望检查是否使用序列或标识或Hilo方案生成ID。所有这些听起来都比你描述的好。谢谢你的回答。我希望有一个非数据库特定的解决方案,因为这将需要在不同供应商的数据库上运行,但似乎没有。FOR UPDATE似乎可以在MySQL和Oracle上工作,在SQL Server上使用WITH(UPDLOCK),同时捕获死锁异常并重新运行代码。