首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >java.sql.Connection隔离级别

java.sql.Connection隔离级别
EN

Stack Overflow用户
提问于 2013-02-09 22:54:39
回答 1查看 3.1K关注 0票数 3

我正在写一些尖峰代码,这些代码没有给我带来我期望的结果。

我有一个表,基本上就是几行计数器。当我运行下面的代码时,我所期望的是第一个到达select语句的线程将获得该行或表上的锁,从而停止对唯一ID值的所有读取或写入。然而,第二个线程总是在第一个线程之前完成,因为它被休眠了1秒,因此它们都读取和写入相同的值,所以它只增加一次,而不是我预期的两次。

是我的代码有问题,还是我对隔离级别的理解不正确?

我已经删除了样板代码。使用MySQL数据库的标准sql.Connection。

代码语言:javascript
复制
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调用的

代码语言:javascript
复制
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();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-09 23:00:57

即使在SERIALIZABLE隔离级别中,也可以并行进行多个选择。如果要在select子句的行上设置锁,请使用select ... for update

参考文献:

http://dev.mysql.com/doc/refman/5.1/en/select.html

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

http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html#isolevel_serializable

可串行化

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14789321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档