开发Java应用,多线程共享同一个Connection,会出现并发问题。
如果线程 A 更新表 T 中的记录 1,同时线程 B 对表 T 中的记录 1 发出 SELECT,我如何确保线程 B 读取线程 A 的更新值?
java.sql.Connection 提供带有 begin()、commit() 和 rollback() 的事务,但是这个过程是否也包括数据正确性?
我想我错过了什么。
最佳答案
两点:
- 您不应该在线程之间共享一个
jdbc.Connection
,至少对于任何“认真生产”的代码,请参见here .出于演示目的,我认为共享一个连接是可以的; - 如果一个线程在提交相关数据库事务后从数据库读取,它将看到另一个线程写入的数据。
第二个问题
will thread B timeout until the first transaction has commit() or rollback()
-- B
将阻塞直到 A
tx 完成(通过提交或回滚),如果:
B
尝试更新/删除A
正在更新的同一表行,并且...A
使用SELECT ... FOR UPDATE
在 DB 级锁定下更新该行。
您可以使用两个控制台(例如,使用 PostgreSQL psql
)获得此行为,每个控制台代表一个线程:
在 A
控制台中输入以下内容:
BEGIN;
SELECT some_col FROM some_tbl WHERE some_col = some_val FOR UPDATE;
现在在 B
控制台类型:
BEGIN;
UPDATE some_tbl SET some_col = new_val WHERE some_col = some_val;
您应该看到 UPDATE
一直阻塞,直到您在 A
中执行了 COMMIT
或 ROLLBACK
。
上面的解释使用了单独的DB连接,就像Java JDBC连接池一样。我认为,当您在 Java 线程之间共享单个连接时,如果连接被其他线程使用,与 DB 的任何交互都会被阻塞。
关于java - 多线程环境中的 JDBC 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46217941/