JDBC之Connection
Connection
Java连接MySQL
Connection必备知识点
使用MySQLClient发送指令给MySQLServer,可以通过connection进行SQL操作,也可以进行事务等操作。
但是下面首先了解以下知识点:
连接方式:在Java中,使用了java.sql.Connection实例来表示应用和数据库的一个连接,通信的方式目前基本上采用的是TCP/IP 连接方式。
连接创建时间:java连接MySQL从发送请求到响应,经过多次测试,平均消耗时间为0.1S。要知道在程序中0.1S占比是很大的。
长链接:通过上面的测试,可以知道,客户端连接到服务端的一个连接,是一个长链接。这是一个很消耗性能和时间的事情。因为MySQL服务端需要当前连接分配资源并对资源进行管理。
超时时间:通过上面的描述,如果在长连接内,客户端没有指令发出,要超过服务端的数据。那么MySQL客户端也会做出对应的措施来断掉来自客户端连接
客户端如果长时间不发送command到Server端,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。
查看wait_timeout对应的SQL:
mysql> show global variables like "wait_timeout";
mysql>set global wait_timeout=28800; 设置全局服务器关闭非交互连接之前等待活动的秒数
利用JDBC使用Connection
概念:接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。
作用:
- 1、创建执行SQL的对象(Statement[普通]、PreparedStatement[预编译]、CallableStatement[存储过程]);
- 2、事务操作:(1)setAutoCommit、commit/rollback (2)设置隔离级别[无用]
- 3、设置事务回滚点
- 4、关闭连接:close
问题一:为什么Java操作数据库的连接不是越多越好
手动创建Java连接数据库的connection连接,会带来问题。
应用程序和数据库之间建立 Connection连接,而数据库机器会为之分配一定的线程资源来维护这种连接,连接数越多,消耗数据库的线程资源也就越多;
另外不同的connection实例之间,可能会操作相同的表数据,也就是高并发,为了支持数据库对ACID特性的支持,数据库又会牺牲更多的资源。
简单地来说,建立Connection连接,会消耗数据库系统的如下资源:
| 资源 | 说明 |
|---|---|
| 线程数 | 线程越多,线程的上下文切换会越频繁,会影响其处理能力 |
| 创建Connection的开销 | 由于Connection负责和数据库之间的通信,在创建环节会做大量的初始化 ,创建过程所需时间和内存资源上都有一定的开销 |
| 内存资源 | 为了维护Connection对象会消耗一定的内存 |
| 锁占用 | 在高并发模式下,不同的Connection可能会操作相同的表数据,就会存在锁的情况,数据库为了维护这种锁会有不少的内存开销 |
上述的几种资源会限制数据库的链接数和处理性能。
结论: 数据库资源是比较宝贵的有限资源,当应用程序有数据库连接需求过大时,很容易会达到数据库的连接并发瓶颈。
所以这也是为什么要使用数据库连接池的原因
问题二、数据库最多支持多少Connection连接
以 MYSQL为例,可以通过如下语句查询数据库的最大支持情况:
-- 查看当前数据库最多支持多少数据库连接
show variables like '%max_connections%';
-- 设置当前运行时mysql的最大连接数,服务重启连接数将还原
set GLOBAL max_connections = 200;
-- 修改 my.ini 或者my.cnf 配置文件
max_connections = 200;
具体的设置范围,应当具体的业务背景来调优。
问题三、数据库连接connection执行SQL的顺序
上面也说过,MySQLClient连接到MySQLServer时,在长连接内,客户端没有指令发出,要超过服务端的数据。那么MySQL客户端也会做出对应的措施来断掉来自客户端连接。默认时间是8小时。
也就是说,客户端在持有连接八小时内,没有执行任何命令,那么服务端就会断掉对应的连接。
如果时不时的给MySQL服务端发送一些无用的查询SQL,那么MySQL就会认为当前数据库连接是在起到作用的
我觉得这就是使用数据库连接池的操作过程,为了防止断开数据库连接
那么我们可以给一个数据库连接connection定义一个生命周期。从创建出来数据库连接开始到断开数据库连接之间称之为数据库连接的生命周期。
场景一、一个线程操作一个数据库连接
自动提交
一个线程在持有数据库连接中,默认是在MySQL默认隔离级别下,对于增删改查的SQL来说,都是按照下面的流程来执行

默认添加上了begin和commit/rollback,针对的是每一条增删改查的SQL。
如以下SQL:
select * from account;
update account set name = 'xxx' where id = 1;
select * from account;
那么按照上面的执行流程,在数据库中真实的指令应该如下所示:
begin;
select * from account;
commit/rollback;
begin;
update account set name = 'xxx' where id = 1;
commit/rollback;
begin;
select * from account;
commit/rollback;
问题以及弊端
首先需要知道的是,在上面的三条SQL中,只有一个update操作会创建事务id,对于查询来说不会创建事务id。
那么创建数据库事务id,也需要消耗性能,可以忽略不计。
但是如果想要实现一组SQL是属于同一个事务中的,也就是想让一批SQL的执行是原子性的。要么是同时成功,要么是同时失败,那么就需要手动的来开启事务。
手动提交[开启事务]
按照上面的分析接着向下走,原始一组SQL如下所示:
select * from account;
update account set name = 'xxx' where id = 1;
select * from account;
那么如果手动开启了事务的执行流程应该如下所示:
begin;
select * from account;
update account set name = 'xxx' where id = 1;
select * from account;
commit/rollback;
对于上面的只会创建一个事务id,那么创建事务的性能消耗更能够忽略不计了。
场景二、多个线程操作同一个数据库连接
多个线程操作同一个数据库连接,我们理想的情况是下面这样子

但是也可能存在下面这种情况:

thread_1和thread_2在交叉执行,那么来列表说明一下情况:
用上面的SQL来进行举例说明:
select * from account;
update account set name = 'xxx' where id = x;
select * from account;
| thread_1 | thread_2 |
|---|---|
| begin | |
| select * from account; | begin; |
| update account set name = 'xxx' where id = 1; | |
| select * from account; | |
| update account set name = 'xxx' where id = 2; | |
| select * from account; | |
| commit | |
| select * from account; | |
| rollback; |
本来thread_2中应该执行的SQL是:
select * from account;
update account set name = 'xxx' where id = 2;
select * from account;
但是现在执行的却是:
select * from account;
update account set name = 'xxx' where id = 1;
update account set name = 'xxx' where id = 2;
select * from account;
但是因为thread_2将其中的一条SQL给提交了,那么就造成了对持有同一个数据库连接的事务造成了影响,但是这又是别的线程所不知道的情况。
但是thread_1又将数据进行了回滚,那么就造成了数据安全问题
解决方式
如果是单机应用的话,可以采用syncronized关键字、lock锁来进行解决,但是只针对于单机应用来说。
如果是分布式架构,那么就需要通过分布式锁来进行解决;
对应的伪代码如下所示:
java.sql.Connection sharedConnection = <创建流程>
## thread #1 的业务伪代码:
synchronized(sharedConnection){
try{
begin;
` update xxx`;
`update yyy`;
`commit`;
} catch(Exception e){
`rollback`;
}
}
## thread #2 的业务伪代码:
synchronized(sharedConnection){
try{
begin;
`delete zzz`;
`insert ttt`;
`rollback`;
} catch(Exception e){
`rollback`;
}
}
小结
综上所述,解决多个线程访问同一个Connection对象时,必须遵循两个基本原则:
1、以资源互斥的方式访问Connection对象;
2、在线程执行结束时,应当最终及时提交(commit)或回滚(rollback)对Connection的影响;不允许存在尚未被提交或者回滚的语句。
问题四、线程生命周期和数据库连接生命周期
我们最容易理解的是:请求------>controller---->service----->dao---->响应
上述我们可以理解一个线程的生命周期,但是相对比来说,我们的数据库连接只是在其中占据了很小的一部分。
那么我们可以总结出来:线程的执行时间远远大于数据库连接执行SQL的时间。
画图如下所示:

这种情况就会出现狼多肉少的情况,那么就可能会导致多个线程公用一个数据库连接的情况。
总结

JDBC之Connection的更多相关文章
- JDBC driver connection string大全
Database / data source URL format / driver name Value Default port MySQL URL format: jdbc:mysql: ...
- atitit.故障排除------有时会错误com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: soc
atitit.故障排除------有时会错误com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: soc ...
- jdbc 获取connection 对象的三种方式
获取数据库连接方法一:驱动实现类 //创建mysql的Driver对象 Driver driver=new com.mysql.jdbc.Driver(); //jdbc url 定位一个数据库: S ...
- jdbc、Connection pool、jndi的理解和关系
一.概念和理解: ①.jdbc:Java Data Base Connectivity,java数据库连接,最为传统的一种方式,直接连接操作数据库,需要连接时创建连接,使用结束时销毁连接. ②.Con ...
- JDBC:Connection.close()
https://www.2cto.com/database/201501/369246.html Connection对象在执行close() 方法之后,并不是直接把Connection对象设置为nu ...
- Weblogic常见故障常:JDBC Connection Pools(转)
WebLogic Server中数据库连接池是一个经常出问题的地方,总结一下出问题的原因和解决办法. 一.数据库连接泄漏 此类问题一般都是由于开发人员没有正确关闭数据库连接造成的.比如使用完Conne ...
- Weblogic常见故障一:JDBC Connection Pools
最近系统老是出现数据库连接池不够用的问题,由于weblogic数据源里没有配置JDBC连接数,取的是默认值15,太小导致connection耗尽,是不是就报一堆错.后来通过修改WebLogic数据源配 ...
- [原理][源代码解析]spring中@Transactional,Propagation.SUPPORTS,以及 Hibernate Session,以及jdbc Connection关系---转载
问题: 一. 1. Spring 如何处理propagation=Propagation.SUPPORTS? 2. Spring 何时生成HibernateSession ? 3. propagati ...
- [原理][来源解析]spring于@Transactional,Propagation.SUPPORTS,以及 Hibernate Session,以及jdbc Connection关联
Spring 捆绑Hibernate. 夹: 一. 1. Spring 怎样处理propagation=Propagation.SUPPORTS? 2. Spring 何时生成HibernateSe ...
- Weblogic常见故障常:JDBC Connection Pools【转】
WebLogic Server中数据库连接池是一个经常出问题的地方,总结一下出问题的原因和解决办法. 一.数据库连接泄漏 此类问题一般都是由于开发人员没有正确关闭数据库连接造成的.比如使用完Conne ...
随机推荐
- 解决scroll中addEventListener不生效的问题
这样写会出现一个情况,滚动的时候不打印任何值,并没有进入具体方法 但是下面这种方法 加一个true就会打印出相应的值
- Kmeans中文聚类
中文文本kmeans聚类原理:K就是将原始数据分为K类,Means即均值点.K-Means的核心就是将一堆数据聚集为K个簇,每个簇中都有一个中心点称为均值点,簇中所有点到该簇的均值点的距离都较到其他簇 ...
- finalshell如何查看密码
1.右键点击导出 2.打开导出的配置文件,搜索password,找到password的编码后的字符串复制 3.运行下面代码,即可查看原来的密码,把main()方法的字符串替换成上一步复制的字符串imp ...
- 硬件IIC调试问题排查
目录 沁恒蓝牙系列芯片中目前只有CH582/583以及208包含有硬件IIC外设,本文均使用582进行测试,其他沁恒芯片也可以参考本文排查. 先进行"常规"检查,检查相关引脚的焊接 ...
- Java密码加密的两种保存方式
密码加密的两种方式(md5和base64) 常见的加密方式有盐值,md5和jdk自带的base64,这里我记录的是base64如何使用,以及破解的方式,话不多说,直接贴代码! 其实md5和加盐值都差不 ...
- Dapper、EF、WebAPI转载记录
轻量级框架Dapper基础 https://www.cnblogs.com/Sinte-Beuve/p/4231053.html 基本使用 https://www.cnblogs.com/hxzb ...
- Spring Boot 开启后缀匹配模式
项目原有 Java 配置为继承 WebMvcConfigurationSupport, 而WebMvcConfigurationSupport#requestMappingHandlerMapping ...
- 19JS输出杨辉三角
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- 模拟ATM系统 —— 用户注册、登录和用户操作页设计 、查询账号、退出账号功能
开发工具:idea 一.项目步骤: 1.系统准备.首页设计 2.用户开户功能 3.用户登录功能 4.用户操作页设计 .查询账号.退出账号功能 5.用户存款功能 6.用户取款功能 7.用户转账功能 8. ...
- idea远程连接云服务器,并将本地代码部署在云端进行运算
电脑内存和显存过小,需要在云服务器进行运算我的模型,由于一直在自己的电脑上写的代码,于是之间迁移代码到云服务器,只要通过ssh链接到云端后,将python解释器使用云端的解释器就ok 从 file-- ...