多线程环境中的JDBC交易



开发一个Java应用程序,该应用程序在Mutiple线程之间共享单个连接,并发问题出现。

如果线程a更新记录1中的记录1,并且同时thread B在表T中的记录1上选择A选择A,则如何确保线程B读取线程A?

的更新值

java.sql.connection提供与begin(),commit()和回滚()的交易,但是此过程是否涵盖数据正确性?

我认为我缺少一些东西。

两个点:

  1. 您不应该在线程之间共享jdbc.Connection,至少对于任何"认真生产"代码,请参见此处。出于演示目的,我认为共享连接还可以;
  2. 如果实施相关数据库事务后,线程从db读取,它将看到另一个线程编写的数据。

对于您的第二个问题

将线程b超时直到第一个交易具有commit()或回滚()

- B将阻止直到A TX完成(通过提交或回滚),如果:

  1. B试图更新/删除由A更新的同一表行,并且...
  2. 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中进行COMMITROLLBACK

上面的解释使用单独的DB连接,就像Java JDBC连接池一样。当您在Java线程之间共享单个连接时,我认为,如果某些其他线程使用连接,与DB的任何交互都会阻塞。

jdbc是一个广泛采用但依从性不平衡的标准,对安全的陈述做出详尽的陈述可能不好。

我不会预期可以防止用多个线程制成的语句执行和提交和回滚。最好的情况是,只有一个线程可以一次使用该连接,而其他线程可以使多线程无用。

如果您不想提供与每个线程的连接,则可以让线程将工作项目提交为由单个工作线程处理所有JDBC工作所消耗的队列。但是,引入连接池可能对现有代码的影响较小。

通常,如果您同时进行更新和读取,则它们会按照它们发生的顺序进行。锁定和隔离级别为并发交易提供一致性保证,但是如果尚未开始交易但这些交易尚不适用。您可以在每行上有一个状态标志,版本号或时间戳,以指示何时发生更新。

如果您有很多更新,最好将它们收集在平面文件中并执行批量副本。它可以比使用JDBC快得多。然后,更新删除了JDBC中的执行选择。

最新更新