Is java.sql.Connection Thread-Safe? – java.sql.Connection是线程安全的吗?

最后修改: 2021年 7月 21日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

When we work on multi-threading projects, we know that if multiple threads share objects that are not implemented with thread safety in mind, the threads may behave unexpectedly.

当我们从事多线程项目时,我们知道如果多个线程共享的对象没有考虑到线程安全的实现,那么这些线程可能会出现意外的行为

Many of us may have suffered from thread-safe problems. So, the question, “Is this class thread-safe?” often comes to mind.

我们中的许多人可能都遭受过线程安全问题的困扰。因此,”这个类是线程安全的吗?”这个问题经常出现在脑海中。

It’s pretty common for a Java application to access relational databases via JDBC and also make use of multi-threading. In this quick tutorial, we’re going to discuss if java.sql.Connection is thread-safe.

对于一个Java应用程序来说,通过JDBC访问关系型数据库并利用多线程是非常常见的。在这个快速教程中,我们将讨论java.sql.Connection是否是线程安全的。

2. The java.sql.Connection Interface

2.java.sql.Connection接口

When we access databases via JDBC from our applications, we’ll directly or indirectly use java.sql.Connection objects. We rely on these connection objects to execute database operations. Therefore, java.sql.Connection is a pretty important type in JDBC.

当我们通过JDBC从我们的应用程序访问数据库时,我们将直接或间接地使用java.sql.Connection对象。我们依靠这些连接对象来执行数据库操作。因此,java.sql.Connection是JDBC中一个相当重要的类型。

It’s also a common scenario that multiple threads will need to talk to a database concurrently. As a result, we often hear the question, “Is java.sql.Connection thread-safe?”

多个线程需要并发地与数据库对话,这也是一种常见的情况。因此,我们经常听到这样的问题:”java.sql.Connection是线程安全的吗?”

In the next few sections, we’ll take a closer look at this question. Further, we’ll discuss a proper approach to use java.sql.Connection objects among multiple threads so that multiple threads can access the database simultaneously.

在接下来的几节中,我们将对这个问题进行仔细研究。此外,我们将讨论在多个线程之间使用java.sql.Connection对象的正确方法,以便多个线程可以同时访问数据库。

3. Thread Safty and java.sql.Connection

3.线程安全和java.sql.Connection

First of all, let’s talk about thread safety quickly. Thread safety is a programming method. That is, it’s an implementation-related concept. Therefore, we can use different techniques to make an implementation thread-safe — for instance, stateless implementations, immutable implementations, and more.

首先,让我们快速谈论一下线程安全线程安全是一种编程方法。也就是说,它是一个与实现相关的概念。因此,我们可以使用不同的技术来使一个实现成为线程安全的,例如,无状态的实现、不可变的实现等等。

Now, let’s take a look at java.sql.Connection. First of all, it’s an interface — it doesn’t contain any implementation. Therefore, it doesn’t make much sense if we ask in general: “Is java.sql.Connection thread-safe?” We have to check the classes that implement this interface to decide if an implementation is thread-safe or not.

现在,让我们看一下java.sql.Connection。首先,它是一个接口 – 它不包含任何实现。因此,如果我们笼统地问,它并没有什么意义。”java.sql.Connection是线程安全的吗?”我们必须检查实现这个接口的类来决定一个实现是否是线程安全的。

Well, a couple of questions come to mind right away: Which classes implement this interface? Are they thread-safe?

好吧,我马上就想到了几个问题。哪些类实现了这个接口?它们是线程安全的吗?

Usually, we don’t implement the java.sql.Connection interface in our application code. JDBC drivers will implement this interface so that we can get the connection to a specific database, such as SQL Server or Oracle.

通常情况下,我们在应用程序代码中不会实现java.sql.Connection接口。JDBC驱动程序将实现这个接口,这样我们就可以获得与特定数据库的连接,如SQL Server或Oracle。

Therefore, the thread-safety of the Connection implementation is fully dependent on the JDBC drivers.

因此,Connection实现的线程安全完全依赖于JDBC驱动程序。

Next, we’ll explore a couple of database JDBC drivers as examples.

接下来,我们将以几个数据库的JDBC驱动为例进行探讨。

4. java.sql.Connection Implementation Examples

4.java.sql.Connection实现实例

Microsoft SQL Server and Oracle Database are two widely used relational database products.

Microsoft SQL Server和Oracle数据库是两个广泛使用的关系型数据库产品。

In this section, we’ll look at the JDBC drivers of these two databases and discuss if their implementations of the java.sql.Connection interface is thread-safe.

在本节中,我们将查看这两个数据库的JDBC驱动程序,并讨论它们对java.sql.Connection接口的实现是否是线程安全的。

4.1. Microsoft SQLServer

4.1 Microsoft SQLServer

The Microsoft SQL Server driver class, SQLServerConnection, implements the java.sql.Connection interface and is not thread-safe, according to its Javadoc:

Microsoft SQL Server的驱动类,SQLServerConnection,实现了java.sql.Connection接口,根据其Javadoc,它不是线程安全的。

SQLServerConnection is not thread-safe, however multiple statements created from a single connection can be processing simultaneously in concurrent threads.

SQLServerConnection不是线程安全的,但是从一个连接中创建的多个语句可以在并发的线程中同时处理。

So, this means we shouldn’t share an SQLServerConnection object among threads, but we can share the statements created from the same SQLServerConnection object.

所以,这意味着我们不应该在线程之间共享一个SQLServerConnection对象,但是我们可以共享从同一个SQLServerConnection对象创建的语句

Next, let’s take a look at another well-known database product, Oracle Database.

接下来,让我们来看看另一个著名的数据库产品–Oracle数据库。

4.2. Oracle Database

4.2.甲骨文数据库

The official Oracle JDBC driver implements the java.sql.Connection interface in a thread-safe way.

官方的Oracle JDBC驱动程序以线程安全的方式实现了java.sql.Connection接口。

Oracle states the thread safety of its Connection implementation in its official document:

Oracle在其官方文件中说明了其Connection实现的线程安全。

The Oracle JDBC drivers provide full support for, and are highly optimized for, applications that use Java multithreading …

Oracle JDBC驱动程序为使用Java多线程的应用程序提供全面支持,并对其进行了高度优化。

However, Oracle strongly discourages sharing a database connection among multiple threads. Avoid allowing multiple threads to access a connection simultaneously …

然而,Oracle强烈反对在多个线程之间共享一个数据库连接。避免让多个线程同时访问一个连接 …

Well, based on the description above, we can say Oracle’s connection implementation is thread-safe. However, sharing a connection object among multiple threads is “strongly discouraged”.

嗯,根据上面的描述,我们可以说Oracle的连接实现是线程安全的。然而,在多个线程之间共享一个连接对象是 “强烈不鼓励的”

So, from the SQL Server and Oracle examples, we know that we cannot assume that a java.sql.Connection implementation is thread-safe. Then, we may ask, what is the proper approach if we want multiple threads to access a database concurrently? Let’s figure it out in the next section.

因此,从SQL Server和Oracle的例子中,我们知道我们不能假设java.sql.Connection实现是线程安全的。那么,我们可能会问,如果我们想让多个线程并发地访问数据库,正确的方法是什么?让我们在下一节中弄清楚。

5. Using a Connection Pool

5.使用连接池

When we access a database from our application, we need first to establish the connection to the database. This is considered an expensive operation. To improve the performance, usually, we’ll use a connection pool.

当我们从我们的应用程序访问数据库时,我们首先需要建立与数据库的连接。这被认为是一个昂贵的操作。为了提高性能,通常,我们会使用连接池

Let’s quickly understand how a connection pool works in a multi-threading scenario.

让我们快速了解连接池在多线程情况下是如何工作的。

A connection pool holds multiple connection objects. We can configure the size of a pool.

一个连接池持有多个连接对象。我们可以配置一个池的大小。

When multiple threads need to access a database concurrently, they request connection objects from the connection pool.

当多个线程需要并发访问一个数据库时,它们会从连接池中请求连接对象。

If there are still free connections in the pool, a thread will get a connection object and start its database operations. After the thread finishes its work, it’ll return the connection to the pool.

如果池子里还有空闲的连接,一个线程将得到一个连接对象并开始它的数据库操作。在线程完成其工作后,它将把连接返回到池中。

In case there is no free connection in the pool, the thread will wait for a connection object to be returned to the pool by another thread.

如果池中没有空闲的连接,线程将等待另一个线程将连接对象返回到池中。

Therefore, a connection pool allows multiple threads to access the database concurrently using different connection objects instead of sharing the same one.

因此,连接池允许多个线程使用不同的连接对象并发地访问数据库,而不是共享同一个连接对象

Further, in this way, we don’t have to care about whether the implementation of the Connection interface is thread-safe.

此外,通过这种方式,我们不必关心Connection接口的实现是否是线程安全的。

6. Conclusion

6.结语

In this article, we’ve discussed the frequently asked question: Is java.sql.Connection thread-safe?

在这篇文章中,我们讨论了经常被问到的问题。java.sql.Connection是线程安全的吗?

As java.sql.Connection is an interface, it’s not easy to predict if the implementations are thread-safe.

由于java.sql.Connection是一个接口,所以不容易预测其实现是否是线程安全的。

Moreover, we’ve addressed that a connection pool is a proper way to handle connections if multiple threads need to access the database concurrently.

此外,我们已经谈到,如果多个线程需要并发访问数据库,连接池是处理连接的一种适当方式。