简体   繁体   English

多线程环境中的JDBC事务

[英]JDBC transactions in multi-threaded environment

Developing a Java application that share a single Connection between mutiple threads, the problem of concurrency arise. 开发在多个线程之间共享单个连接的Java应用程序时,会出现并发问题。

If thread A updates record 1 in table T, and simultaneously thread B issues a SELECT on record 1 in table T, how do I ensure thread B reads the updated values of thread A? 如果线程A更新表T中的记录1,并且线程B同时对表T中的记录1发出SELECT,我如何确保线程B读取线程A的更新值?

java.sql.Connection offers transactions with begin(), commit() and rollback(), but does this process also cover data correctness? java.sql.Connection提供带有begin(),commit()和rollback()的事务,但是此过程还涵盖数据正确性吗?

I think I'm missing something. 我想我缺少了一些东西。

Two points: 两点:

  1. You shouldn't share a jdbc.Connection between threads, at least for any 'seriously production' code, see here . 您不应在线程之间共享jdbc.Connection ,至少对于任何“严重生产”代码而言,请参见此处 For demo purposes, I think, sharing a Connection is OK; 出于演示目的,我认为共享连接是可以的;
  2. If a thread reads from DB after relevant DB transaction is committed, it will see data written by another thread. 如果一个线程在相关的数据库事务提交后从数据库读取,它将看到另一个线程写入的数据。

For your second question 关于第二个问题

will thread B timeout until the first transaction has commit() or rollback() 将线程B超时,直到第一个事务具有commit()或rollback()

-- B will block till A tx is finished (either by commit or rollback) if: -在以下情况下, B将阻塞直到A tx完成(通过提交或回滚):

  1. B tries to update/delete same table row which is being updated by A , and ... B尝试更新/删除A正在更新的同一表行,然后...
  2. A updates that row under DB-level lock, using SELECT ... FOR UPDATE . A更新,下DB级锁行,使用SELECT ... FOR UPDATE

You can get this behavior using two consoles (for example, with PostgreSQL psql ), each console stands for a thread: 您可以使用两个控制台(例如,使用PostgreSQL psql )来获得此行为,每个控制台代表一个线程:

in A console type following: A控制台类型如下:

BEGIN;
SELECT some_col FROM some_tbl WHERE some_col = some_val FOR UPDATE;

now in B console type: 现在在B控制台中输入:

BEGIN;
UPDATE some_tbl SET some_col = new_val WHERE some_col = some_val;

You should see that UPDATE blocks until in A you do either COMMIT or ROLLBACK . 您应该看到UPDATE块,直到在A执行COMMITROLLBACK为止。

Above explanation uses separate DB connections, just like Java JDBC connection pool. 上面的解释使用了单独的数据库连接,就像Java JDBC连接池一样。 When you share single connection between Java threads, I think, any interaction with DB will block if connection is used by some other thread. 我认为,当您在Java线程之间共享单个连接时,如果其他某个线程使用了连接,则与DB的任何交互都会阻塞。

Jdbc is a standard that is broadly adopted but with uneven levels of adherence, it is probably not good to make sweeping statements about what is safe. Jdbc是被广泛采用的标准,但是遵循的标准不均衡,因此对安全性进行大胆的陈述可能不好。

I would not expect there is anything to keep statement executions and commits and rollbacks made from multiple threads from getting interleaved. 我不希望有任何方法可以防止语句执行以及由多个线程进行的提交和回滚被交错。 Best case, only one thread can use the connection at a time and the others block, making multithreading useless. 最好的情况是,一次只有一个线程可以使用该连接,而其他线程则阻塞,从而使多线程无用。

If you don't want to provide a connection to each thread, you could have the threads submit work items to a queue that is consumed by a single worker thread handling all the jdbc work. 如果您不想提供与每个线程的连接,则可以让线程将工作项提交到队列,该队列由处理所有jdbc工作的单个工作线程使用。 But it's probably less impact on existing code to introduce a connection pool. 但是引入连接池对现有代码的影响可能较小。

In general if you have concurrent updates and reads then they happen in the order that they happen. 通常,如果您具有并发更新和读取,则它们将按照发生的顺序发生。 Locking and isolation levels provide consistency guarantees for concurrent transactions but if one hasn't started its transaction yet those aren't applicable. 锁定和隔离级别为并发事务提供了一致性保证,但是如果尚未开始其事务但这些事务将不适用。 You could have a status flag, version number, or time stamp on each row to indicate when an update occurred. 您可能在每行上都有状态标志,版本号或时间戳,以指示何时发生更新。

If you have a lot of updates it can be better to collect them in a flat file and execute a bulk copy. 如果您有很多更新,最好将它们收集在一个平面文件中并执行批量复制。 It can be much faster than using jdbc. 它可能比使用jdbc快得多。 Then with updates out of the way execute selects in jdbc. 然后在不进行更新的情况下在jdbc中执行select。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM