Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多线程环境中的JDBC事务_Java_Multithreading_Jdbc_Transactions - Fatal编程技术网

Java 多线程环境中的JDBC事务

Java 多线程环境中的JDBC事务,java,multithreading,jdbc,transactions,Java,Multithreading,Jdbc,Transactions,开发一个在多个线程之间共享单一连接的Java应用程序时,会出现并发问题 如果线程A更新表T中的记录1,同时线程B对表T中的记录1发出SELECT,我如何确保线程B读取线程A的更新值 java.sql.Connection提供了begin、commit和rollback事务,但是这个过程是否也包括数据正确性 我想我遗漏了什么。两点: 您不应该在线程之间共享jdbc.Connection,至少对于任何“正式生产”代码,请参阅。出于演示目的,我认为,共享连接是可以的; 如果一个线程在提交相关DB事务后

开发一个在多个线程之间共享单一连接的Java应用程序时,会出现并发问题

如果线程A更新表T中的记录1,同时线程B对表T中的记录1发出SELECT,我如何确保线程B读取线程A的更新值

java.sql.Connection提供了begin、commit和rollback事务,但是这个过程是否也包括数据正确性

我想我遗漏了什么。

两点:

您不应该在线程之间共享jdbc.Connection,至少对于任何“正式生产”代码,请参阅。出于演示目的,我认为,共享连接是可以的; 如果一个线程在提交相关DB事务后从DB中读取数据,它将看到另一个线程写入的数据。 关于你的第二个问题

线程B将超时,直到第一个事务完成提交或回滚

-在以下情况下,B将通过提交或回滚阻止,直到发送完成:

B尝试更新/删除A正在更新的同一表行,并且。。。 使用“选择…”更新数据库级别锁定下的该行。。。更新。 您可以使用两个控制台获得此行为,例如,对于PostgreSQL psql,每个控制台代表一个线程:

在控制台中,请键入以下内容:

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;
您应该看到,在执行提交或回滚之前,更新会一直阻塞


上面的解释使用单独的数据库连接,就像JavaJDBC连接池一样。我认为,当您在Java线程之间共享单个连接时,如果连接被其他线程使用,则与DB的任何交互都将被阻止。

Jdbc是一个被广泛采用的标准,但遵守程度参差不齐,对什么是安全的做出全面的声明可能并不好

我不希望有任何东西可以阻止多线程执行语句、提交和回滚过程的交错。最好的情况是,一次只能有一个线程使用连接,而其他线程阻塞连接,这使得多线程处理毫无用处

如果不想为每个线程提供连接,可以让线程将工作项提交到一个队列,该队列由处理所有jdbc工作的单个工作线程使用。但引入连接池可能对现有代码的影响较小

通常,如果您有并发更新和读取,那么它们会按照发生的顺序发生。锁定和隔离级别为并发事务提供了一致性保证,但如果还没有启动事务,则不适用。您可以在每行上都有一个状态标志、版本号或时间戳,以指示更新发生的时间


如果您有很多更新,最好将它们收集到一个平面文件中并执行大容量复制。它可以比使用jdbc快得多。然后,随着更新的进行,执行jdbc中的选择

使用已知连接池不要共享连接。它并不意味着要被共享。事实上,它是用于一个小的演示应用程序。我缺少的是:如果我在线程a中开始一个事务,并且在我从线程B开始另一个事务之后,线程B是否会超时,直到第一个事务完成提交或回滚?或者线程B是否会抛出SQLException?3。Java中的事务是通过使用一个连接的一个线程来实现的。当事务打开时,基础实现调用将在连接上开始。成功返回时,它调用commit,如果出现运行时异常,它将调用rollback。@BorisPavlović理解这个概念。现在又出现了另一个问题。在提交或回滚更改之前,是否从线程a连接开始事务调用并锁定相关记录?或者连接为B的线程B是否仍然能够在不等待线程A提交/回滚的情况下选择这些记录?我想说的是后者,但是,当有一个简单的解决方案来避免风险时,这是无关紧要的。@BorisPavlović可能我把事情复杂化了。这个简单的解决方案是什么?每个线程的连接?从技术上讲,JDBC要求连接是线程安全的,但这并不意味着这些线程彼此隔离。这仍然意味着所有这些线程应该在同一个事务中进行协作,并协调它们的操作,以便它们不会执行干扰的工作,例如一个线程提交一个事务,而另一个线程仍在工作,等等。这使得从多个线程访问单个连接充其量不是很有用,最糟糕的情况是,这里是滋生虫子的种族条件的避风港。