数据库连接池为什么要用 ThreadLocal 呢?(不用会怎样?)

简介: 数据库连接池为什么要用 ThreadLocal 呢?(不用会怎样?)本人是在学threadlocal的时候,网上大部分人都是说数据库连接池是典型的用了threadloca的例子,然后我就又查数据库连接池和

这个问题我疑问了很久很久,主要如下截图。

image.png

我先说为什么引入threadlocal,其实是为了解决数据库事务,而事务是和连接有关的,每个连接对应一个事务,多个连接的事务是不一样的,先大概了解一下,往下看👇

本人是在学threadlocal的时候,网上大部分人都是说数据库连接池是典型的用了threadloca的例子,然后我就又查数据库连接池和threadloca的关系 ,但是,99%都说threadlocal是为了在并发的情况下,为了保证线程安全,创建了副本什么的,其实这只是threadlocal 的用法之一,它还有个用法就是确保同一线程之间参数传递的方便(扯远了)

回归正题,还是拿上面的图来说事。。。。

我只讲两个关键点,明白人一看就懂:

1、两者有根本性的区别,用处不一样!

  • 连接池是缓存并托管数据库连接,主要是为了提高性能。
  • 而ThreadLocal缓存连接,是为了把同一个数据库连接“分享”给同一个线程的不同调用方法。(不管调用哪个方法,都是使用的同一个连接,方便进行“跨方法”的事务控制)

举个栗子:

如果一个请求中涉及多个 DAO 操作,而如果这些DAO中的Connection都是独立的话,就没有办法完成一个事务。但是如果DAO 中的 Connection 是从 ThreadLocal 中获得的(意味着都是同一个对象), 那么这些 DAO 就会被纳入到同一个 Connection 之下。

2、重点要理解“连接池”。

连接池里面有一定数量的连接资源,比如最大20个连接。

题外话:如果直接通过 Java原生API 获取“直连”的话:

(底层方法一般都是这样写的:

java.sql.DriverManager.getConnection(url, props);
   java.sql.Driver.connect(url, props);

特点是:要传入url、用户名和密码等信息)

这种方式,肯定就没有使用数据库连接池。

使用数据库连接池,通常都是得到一个所谓的javax.sql.DataSource[接口]的实例对象,它里面包含了Connection,并且数据库连接池工具类(比如C3P0、JNDI、DBCP等),肯定是重新定义了getConnection、closeConnection等方法,所以你每次得到的Connection,几乎都不是新建立的连接(而是已经建立好并放到缓存里面的连接),你调用closeConnection方法,也不是真正的关闭连接(一般都是起到一个标识作用,标识当前连接已经使用完毕,归还给连接池,让这个连接处于待分配状态)【PS:所以说:使用数据库连接池时,还是要显式的调用数据库连接池API提供的关闭连接的方法】。

理解一下这句话:

不同的线程在同一个时间( 或者 同一个线程在多个地方)从连接池中拿到的Connection,肯定不是同一个连接。(反过来讲:不同时间的两个线程,一前一后,则有可能拿到同一个连接)

总结:

再好好理解一下上面的一段话,我再最后解释亿下。。。


  • 首先,我们为了避免单一数据库连接的创建和关闭耗费时间和性能,引入了数据库连接池,提前创建好了n条连接放入池中,如果是单线程情况下,那这样挺好的
  • 那如果是多线程情况下呢?还是上面那段话,假设同一时间多个线程从数据库连接池获取连接,那肯定拿的是不同的连接,我当前线程和别的线程拿的连接不一样,那我当前在crud的时候,不在一个事务之内。
  • 假设不同时间的多个线程要从数据库连接池拿连接,那这个时候就可能拿到的是同一个连接了,那我多个线程线程拿到的是同一个连接,也就是说在多个线程在同一个事务之内,线程a执行了插入 还没来得及提交,线程b此时来了个更新 ,在线程a还未操作完之前,线程b更新完了后,直接把连接给close了,线程a插了一半发现插不了了。。。此时肯定在想,这™是谁在搞我。
  • 为了确保不同时间多个线程可能拿到的是同一个连接,那么此时threadlocal 闪亮登场,就算我拿的是“同一个连接”,在引入了threadlocal后,每个线程之间都会创建独立的连接副本,将collection各自copy一份,这样就互相不干扰了。
相关文章
|
7月前
|
Java 关系型数据库 MySQL
【数据库连接,线程,ThreadLocal三者之间的关系】
【数据库连接,线程,ThreadLocal三者之间的关系】
108 0
|
缓存 安全 Java
数据库连接池为啥要用 ThreadLocal?
这个问题我疑问了很久很久,主要如下截图。
154 0
数据库连接池为啥要用 ThreadLocal?
|
26天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
34 1
|
29天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
39 4
|
2月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
69 3
Mysql(4)—数据库索引
|
1月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
193 1
|
1月前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
100 2
|
1月前
|
存储 关系型数据库 MySQL
MySQL vs. PostgreSQL:选择适合你的开源数据库
在众多开源数据库中,MySQL和PostgreSQL无疑是最受欢迎的两个。它们都有着强大的功能、广泛的社区支持和丰富的生态系统。然而,它们在设计理念、性能特点、功能特性等方面存在着显著的差异。本文将从这三个方面对MySQL和PostgreSQL进行比较,以帮助您选择更适合您需求的开源数据库。
137 4
|
23天前
|
运维 关系型数据库 MySQL
安装MySQL8数据库
本文介绍了MySQL的不同版本及其特点,并详细描述了如何通过Yum源安装MySQL 8.4社区版,包括配置Yum源、安装MySQL、启动服务、设置开机自启动、修改root用户密码以及设置远程登录等步骤。最后还提供了测试连接的方法。适用于初学者和运维人员。
142 0
|
2月前
|
存储 关系型数据库 MySQL
如何在MySQL中创建数据库?
【10月更文挑战第16天】如何在MySQL中创建数据库?