JDBC的超时原理
1.什么是JDBC
jdbc是业务系统连接数据的标准API。SUN公司一共定义了4中类型的JDBC:JDBC-ODBC桥;Native-API 驱动;Network-Protocol 驱动;Database-Protocol 驱动;我们主要使用的是第4种,该类型的Driver完全由Java代码实现,通过使用socket与数据库进行通信。
JDBC通过socket对字节流进行处理,因此也会有一些基本网络操作,类似于HttpClient这种用于网络操作的代码库。当在网络操作中遇到问题的时候,将会消耗大量的cpu资源,并且失去响应超时。如果你之前用过HttpClient,那么你一定遇到过未设置timeout造成的错误。同样,第4种类型的JDBC,若没有合理地设置socket timeout,也会有相同的错误——连接被阻塞。 接下来,就让我们来学习一下如何正确地设置socket timeout,以及需要考虑的问题。
上图展示了简化后应用与数据库间的timeout层级。高级别的timeout依赖于低级别的timeout,只有当低级别的timeout无误时,高级别的timeout才能确保正常。例如,当socket timeout出现问题时,高级别的statement timeout和transaction timeout都将失效。 statement timeout无法处理网络连接失败时的超时,它能做的仅仅是限制statement的操作时间。网络连接失败时的timeout必须交由JDBC来处理。 JDBC的socket timeout会受到操作系统socket timeout设置的影响。
DBCP连接池位于图2的左侧,你会发现timeout层级与DBCP是相互独立的。DBCP负责的是数据库连接的创建和管理,并不干涉timeout的处理。当连接在DBCP中创建,或是DBCP发送校验query检查连接有效性的时候,socket timeout将会影响这些过程,但并不直接对应用造成影响。 当在应用中调用DBCP的getConnection()方法时,你可以设置获取数据库连接的超时时间,但是这和JDBC的timeout毫不相关。
2.什么是Transaction TimeOut
transaction timeout一般存在于框架(Spring, EJB)或应用级。transaction timeout或许是个相对陌生的概念,简单地说,transaction timeout就是“statement Timeout * N(需要执行的statement数量) + @(垃圾回收等其他时间)”。transaction timeout用来限制执行statement的总时长。在Spring中,你可以使用下面展示的XML或是在源码中使用@Transactional注解来进行设置。
<tx:attributes>
<tx:method name=“…” timeout=“3″/>
</tx:attributes>
Spring提供的transaction timeout配置非常简单,它会记录每个事务的开始时间和消耗时间,当特定的事件发生时就会对消耗时间做校验,当超出timeout值时将抛出异常。
Spring中,数据库连接被保存在ThreadLocal里,这被称为事务同步(Transaction Synchronization),与此同时,事务的开始时间和消耗时间也被保存下来。当使用这种代理连接创建statement时,就会校验事务的消耗时间。
3.什么Statement TimeOut
statement timeout用来限制statement的执行时长,timeout的值通过调用JDBC的java.sql.Statement.setQueryTimeout(int timeout) API进行设置。不过现在开发者已经很少直接在代码中设置,而多是通过框架来进行设置。
以iBatis为例,statement timeout的默认值可以通过sql-map-config.xml中的defaultStatementTimeout 属性进行设置。同时,你还可以设置sqlmap中select,insert,update标签的timeout属性,从而对不同sql语句的超时时间进行独立的配置。
4.JDBC的Timeout实现机制
Oracle:
- 通过调用Connection的createStatement()方法创建statement
调用Statement的executeQuery()方法statement通过自身connection将query发送给Oracle数据库
statement在OracleTimeoutPollingThread(每个classloader一个)上进行注册
达到超时时间
OracleTimeoutPollingThread调用OracleStatement的cancel()方法
通过connection向正在执行的query发送cancel消息
SQLServer:与oracle类似
MySql:
- 通过调用Connection的createStatement()方法创建statement
调用Statement的executeQuery()方法statement通过自身connection将query发送给MySQL数据库
statement创建一个新的timeout-execution线程用于超时处理
5.1版本后改为每个connection分配一个timeout-execution线程
向timeout-execution线程进行注册
达到超时时间
TimerThread调用JtdsStatement实例中的TsdCore.cancel()方法
timeout-execution线程创建一个和statement配置相同的connection
使用新创建的connection向超时query发送cancel query(KILL QUERY “connectionId”)
CUBRID:与MYSQL类似
5.JDBC的Socket TimeOut
第4种类型的JDBC使用socket与数据库连接,数据库并不对应用与数据库间的连接超时进行处理。
JDBC的socket timeout在数据库被突然停掉或是发生网络错误(由于设备故障等原因)时十分重要。由于TCP/IP的结构原因,socket没有办法探测到网络错误,因此应用也无法主动发现数据库连接断开。如果没有设置socket timeout的话,应用在数据库返回结果前会无期限地等下去,这种连接被称为dead connection。
为了避免dead connections,socket必须要有超时配置。socket timeout可以通过JDBC设置,socket timeout能够避免应用在发生网络错误时产生无休止等待的情况,缩短服务失效的时间。
不推荐使用socket timeout来限制statement的执行时长,因此socket timeout的值必须要高于statement timeout,否则,socket timeout将会先生效,这样statement timeout就变得毫无意义,也无法生效。
下面展示了socket timeout的两个设置项,不同的JDBC驱动其配置方式会有所不同。
- socket连接时的timeout:通过Socket.connect(SocketAddress endpoint, int timeout)设置
- socket读写时的timeout:通过Socket.setSoTimeout(int timeout)设置
通过查看CUBRID,MySQL,MS SQL Server (JTDS)和Oracle的JDBC驱动源码,我们发现所有的驱动内部都是使用上面的2个API来设置socket timeout的。
除了调用DBCP的API以外,还可以通过properties属性进行配置。
通过properties属性进行配置时,需要传入key为“connectionProperties”的键值对,value的格式为“[propertyName=property;]*”。下面是iBatis中的properties配置。
<transactionManager type=“JDBC”>
<dataSource type=“com.nhncorp.lucy.db.DbcpDSFactory”>
….
<property name=“connectionProperties” value=“oracle.net.CONNECT_TIMEOUT=6000;oracle.jdbc.ReadTimeout=6000″/>
</dataSource>
</transactionManager>
6.操作系统级的Socket TimeOut
如果不设置socket timeout或connect timeout,应用多数情况下是无法发现网络错误的。因此,当网络错误发生后,在连接重新连接成功或成功接收到数据之前,应用会无限制地等下去。30分钟后应用的连接问题奇迹般的解决了,这是因为操作系统同样能够对socket timeout进行配置。Linux服务器将socket timeout设置为了30分钟,从而会在操作系统的层面对网络连接做校验,因此即使JDBC的socket timeout设置为0,由网络错误造成的数据库连接问题的持续时间也不会超过30分钟。
通常,应用会在调用Socket.read()时由于网络问题被阻塞住,而很少在调用Socket.write()时进入waiting状态,这取决于网络构成和错误类型。当Socket.write()被调用时,数据被写入到操作系统内核的缓冲区,控制权立即回到应用手上。因此,一旦数据被写入内核缓冲区,Socket.write()调用就必然会成功。但是,如果系统内核缓冲区由于某种网络错误而满了的话,Socket.write()也会进入waiting状态。这种情况下,操作系统会尝试重新发包,当达到重试的时间限制时,将产生系统错误。在我们公司,重新发包的超时时间被设置为15分钟。
JDBC的超时原理的更多相关文章
- JDBC超时原理与设置
抄录自网上,因为担心以后找不到,因此抄录之.感谢分享的大神! 英文原版:http://www.cubrid.org/blog/dev-platform/understanding-jdbc-inter ...
- JDBC:从原理到应用
一.是为何物 1.概念 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用J ...
- 深入理解JDBC的超时设置
恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数据库的各种超时设置及其设置方法做介绍. 真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到DDos攻击后,整个服务都垮掉了.由于第四 ...
- dubbo超时原理以及解决方案
dubbo超时原理以及解决方案 本篇主要记录dubbo中关于超时的常见问题,实现原理,解决的问题 超时问题 为了检查对dubbo超时的理解,尝试回答如下几个问题,如果回答不上来或者不确定那么说明此处需 ...
- SpringBoot 2.X集成 jdbc自动配置原理探究
前言 Springboot对于数据访问层,不管是 SQL还是 NOSQL,Spring Boot 底层都是采用 Spring Data 的方式统一处理.Spring Data 是 Spring 家族中 ...
- 【Mybatis源码解析】- JDBC连接数据库的原理和操作
JDBC连接数据库的原理和操作 JDBC即Java DataBase Connectivity,java数据库连接:JDBC 提供的API可以让JAVA通过API方式访问关系型数据库,执行SQL语句, ...
- JDBC数据库连接池原理
JDBC是java数据库连接的简称.它是一种用于实行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成.其相关的API都在java.sql.*包下 ...
- 黑马程序员—创建JDBC框架及原理分析
对于Java数据库的连接,由最初学习的每次全部手工代码,到后面的不断利用知识简化代码量:这是不断学习的过程,就像人类由原始社会的钻木取火到当代的文明,都是一步步过来的! 本文不从最开始的JDBC入门开 ...
- dubbo源码分析(二):超时原理以及应用场景
dubbo超时原理以及应用场景 *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: ...
随机推荐
- erlang四种监控策略
转自:http://jasionq.blog.163.com/blog/static/10970577920133883158424/ Supervisor Behaviour是一个用来实现一个sup ...
- log4j.properties文件的配置
Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局).这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出.综合使用这三个组件可以轻松 ...
- NYOJ-915 +-字符串(贪心)
+-字符串 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 Shiva得到了两个只有加号和减号的字符串,字串长度相同.Shiva一次可以把一个加号和它相邻的减号交换. ...
- Raft详解-启动后运行期间代码
Raft启动后运行期间主要执行两个函数:1.状态监测和转化 func (rf *Raft) Loop() { // Set out as a follower TimeOutConst := 0 fo ...
- Hadoop上的中文分词与词频统计实践 (有待学习 http://www.cnblogs.com/jiejue/archive/2012/12/16/2820788.html)
解决问题的方案 Hadoop上的中文分词与词频统计实践 首先来推荐相关材料:http://xiaoxia.org/2011/12/18/map-reduce-program-of-rmm-word-c ...
- Flask -- 会话
会话session 在不同请求间存储特定用户的信息.它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名.这意味着用户可以查看你 Cookie 的内容,但却不能修改它,除非用户 ...
- 您可能无法使用服务器管理器,如果两个线程同时访问 IIS 管理 IIS 的修补程序
http://support.microsoft.com/kb/946517 如果多线程操作 win2003 iis 失败, 打上这个补丁就好了
- MYSQL超时连接问题(com.mysql.jdbc.MysqlIO.readFully)
应用服务器连接mysql,有时候会出现以下异常: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.jav ...
- luci 随笔
entry()函数, 第一个参数是定义菜单的显示(Virtual path). 第二个参数定义相应的处理方式(target). alias是指向别的entry的别名,from调用的某一个view,cb ...
- 期刊:DOI :10.3969/j.issn.1001-2400.2012.01.008
DOI:10.3969/j.issn.1001-2400.2012.01.008 “/” 分为前缀和后缀两部分中间用一斜杠分开,前缀中又以小圆点分为两部分. "DOI":一篇期刊论 ...