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