Java sql读取+;写-防止竞争条件?
我有两个线程调用一个方法,该方法在mysql数据库中执行记录的读取和写入。一些伪代码:Java sql读取+;写-防止竞争条件?,java,mysql,Java,Mysql,我有两个线程调用一个方法,该方法在mysql数据库中执行记录的读取和写入。一些伪代码: public void incrementRowValue() { Connection conn = ...; try { conn.setAutoCommit(false); int value = conn.execute("select value from foo where id = 123"); value += 1;
public void incrementRowValue() {
Connection conn = ...;
try {
conn.setAutoCommit(false);
int value = conn.execute("select value from foo where id = 123");
value += 1;
conn.execute("update foo set value = " + value + " where id = 123");
conn.commit();
}
catch (SQLException ex) {
conn.rollback();
}
finally {
conn.close();
}
}
因此,如果线程大约同时执行,则看起来读+写并不是作为一个原子项执行的。例如,当起始值为零时,我的日志显示,如果两个线程几乎同时执行,则结束值可以是1而不是2
我是否可以使用不同的锁定级别来防止这种情况?当然,如果必要的话,我可以用java代码进行同步,但我可能缺少了数据库级别为我们提供的一个重要特性
谢谢
最简单的方法是将SQL封装到一条语句中,让SQL server来处理它,我一时记不起确切的语法,但它可能是这样的:
conn.execute("update foo set value = (select value from foo where id = 123)+1 where id = 123");
SQL server将锁定正在使用的行(如果使用多行,将锁定所有行),并以原子方式执行操作
这也将更快/更高效,因为它只进行一次数据库调用,而不是两次。不过,这种更新实际上需要包装到存储过程中。最简单的方法是将SQL包装到一个语句中,让SQL server处理它,我一时记不起确切的语法,但它可能类似于:
conn.execute("update foo set value = (select value from foo where id = 123)+1 where id = 123");
You can manage database concurrency using isolation levels
Isolation Level Dirty Read Nonrepeatable Read Phantom Read
READ UNCOMMITTED Permitted Permitted Permitted
READ COMMITTED -- Permitted Permitted
REPEATABLE READ -- -- Permitted
SERIALIZABLE
SERIALIZABLE-it provide highest level of concurrency
For details please refer :
[http://www.oracle.com/technetwork/issue-archive/2005/05-nov/o65asktom-082389.html][1]
SQL server将锁定正在使用的行(如果使用多行,将锁定所有行),并以原子方式执行操作
这也将更快/更高效,因为它只进行一次数据库调用,而不是两次。不过,这种更新实际上需要包装到存储过程中。最简单的方法是将SQL包装到一个语句中,让SQL server处理它,我一时记不起确切的语法,但它可能类似于:
conn.execute("update foo set value = (select value from foo where id = 123)+1 where id = 123");
You can manage database concurrency using isolation levels
Isolation Level Dirty Read Nonrepeatable Read Phantom Read
READ UNCOMMITTED Permitted Permitted Permitted
READ COMMITTED -- Permitted Permitted
REPEATABLE READ -- -- Permitted
SERIALIZABLE
SERIALIZABLE-it provide highest level of concurrency
For details please refer :
[http://www.oracle.com/technetwork/issue-archive/2005/05-nov/o65asktom-082389.html][1]
SQL server将锁定正在使用的行(如果使用多行,将锁定所有行),并以原子方式执行操作
这也将更快/更高效,因为它只进行一次数据库调用,而不是两次。不过,这种更新实际上需要包装到存储过程中。最简单的方法是将SQL包装到一个语句中,让SQL server处理它,我一时记不起确切的语法,但它可能类似于:
conn.execute("update foo set value = (select value from foo where id = 123)+1 where id = 123");
You can manage database concurrency using isolation levels
Isolation Level Dirty Read Nonrepeatable Read Phantom Read
READ UNCOMMITTED Permitted Permitted Permitted
READ COMMITTED -- Permitted Permitted
REPEATABLE READ -- -- Permitted
SERIALIZABLE
SERIALIZABLE-it provide highest level of concurrency
For details please refer :
[http://www.oracle.com/technetwork/issue-archive/2005/05-nov/o65asktom-082389.html][1]
SQL server将锁定正在使用的行(如果使用多行,将锁定所有行),并以原子方式执行操作
这也将更快/更高效,因为它只进行一次数据库调用,而不是两次。不过,这种更新实际上需要包装到存储过程中。这就是所谓的丢失更新问题。您可以使用专用锁。这将阻止其他事务读取锁定的数据。这称为丢失更新问题。您可以使用专用锁。这将阻止其他事务读取锁定的数据。这称为丢失更新问题。您可以使用专用锁。这将阻止其他事务读取锁定的数据。这称为丢失更新问题。您可以使用专用锁。这将阻止其他事务读取锁定的数据。我实际尝试执行的代码将使其变得难以处理-是否有任何方法锁定特定行?您需要使用SQL事务。如果设置正确并启动事务,然后访问事务中的行,则它将锁定该行,直到事务结束。不过,我还是建议在一个存储过程中完成整个过程。很抱歉,我没有完全理解-那么我的小示例不应该像现在这样工作吗?它只访问事务中的一行。是的,但这样读取不会锁定该行,您需要为事务设置隔离级别,否则仅从一行读取不会锁定该行。我已经检查了connection.getTransactionIsolation(),它为我返回了事务\u REPEATABLE\u READ。查看文档,看起来该级别应该可以防止脏读。但它并不能阻止幻影读取。这就是我在这里遇到的问题吗?我实际上试图执行的代码会使它变得很难处理-有没有办法锁定特定的行?您需要使用SQL事务。如果设置正确并启动事务,然后访问事务中的行,则它将锁定该行,直到事务结束。不过,我还是建议在一个存储过程中完成整个过程。很抱歉,我没有完全理解-那么我的小示例不应该像现在这样工作吗?它只访问事务中的一行。是的,但这样读取不会锁定该行,您需要为事务设置隔离级别,否则仅从一行读取不会锁定该行。我已经检查了connection.getTransactionIsolation(),它为我返回了事务\u REPEATABLE\u READ。查看文档,看起来该级别应该可以防止脏读。但它并不能阻止幻影读取。这就是我在这里遇到的问题吗?我实际上试图执行的代码会使它变得很难处理-有没有办法锁定特定的行?您需要使用SQL事务。如果设置正确并启动事务,然后访问事务中的行,则它将锁定该行,直到事务结束。不过,我还是建议在一个存储过程中完成整个过程。很抱歉,我没有完全理解-那么我的小示例不应该像现在这样工作吗?它只访问事务中的一行。是的,但这样读取不会锁定该行,您需要为事务设置隔离级别,否则仅从一行读取不会锁定该行。我已经检查了connection.getTransactionIsolation(),它为我返回了事务\u REPEATABLE\u READ。查看文档,看起来该级别应该可以防止脏读。但这并不能阻止潘
You can manage database concurrency using isolation levels
Isolation Level Dirty Read Nonrepeatable Read Phantom Read
READ UNCOMMITTED Permitted Permitted Permitted
READ COMMITTED -- Permitted Permitted
REPEATABLE READ -- -- Permitted
SERIALIZABLE
SERIALIZABLE-it provide highest level of concurrency
For details please refer :
[http://www.oracle.com/technetwork/issue-archive/2005/05-nov/o65asktom-082389.html][1]