数据库连接池 C3P0 小结

译于官方文档

基础连接池配置

  • initialPoolSize : 初始连接数(default 3)
  • minPoolSize :最小连接数(default 3)
  • maxPoolSize :最大连接数(default 15)
  • maxIdleTime :最大闲置时间, 未使用的连接在被丢弃之前在连接池存活时间,单位为秒(default 0, 永久存活)
  • acquireIncrement : 获取连接数量, 连接不足时,c3p0尝试一次获取新连接的个数(default 3)

连接池中的连接数量在min和max之间变化,当用户需要一个连接的时候,如果当前没有可用连接,并且连接池中连接数量未达到上限的时候,连接池会创建一个新的连接。

获取连接十分消耗资源,所以请求量很大的时候,我们应该提高每次新增连接的个数而不是每次只新加一个连接并且让客户端等待。acquireIncrement 决定了每次新增连接的个数,当然这个数量不会图片maxPoolSize的上限。

连接池中的连接在以下情况会被释放

  1. 连接池通过测试发现连接可以断开
  2. 连接池设置了最大闲置时间, 连接超过这个时间未使用
    3.连接太老了...

管理连接池大小和连接生命周期

我们根据不同的需求在性能,占用空间以及可靠性之前做出权限。C3P0提供一系列参数来对"连接池在大量负载以后需要多久将连接数降至最低", "为了提高可靠性,是否主要替换连接池中的'老'连接" 等情景进行控制。

默认情况下, 连接池中的连接不会过期。如果想让连接可以过期,maxIdleTime 和/或maxConnectionAge 都可以使用。maxConnectionAge的区别是连接从创建开始,最大的存活时间, 即使这个连接并不空闲。

在连接池从大量负载闲置下来以后,如果我们想快速清理不需要的连接,可以给maxIdleTimeExcessConnections 设置一个比maxIdleTime小很多的值,强制连接池快速将闲置连接回收。

对于这些timeout的设置的建议:“慢,慢,慢!”。连接池的概念本身就是获取一次连接,然后使用很多很多,很多次。大部分数据库允许连接保持好几个小时或以上。没有必要在几分钟内甚至更短时间回收连接。将maxConnectionAge 或者 maxIdleTime 设置为1800 (30分钟)已经是非常激进的了。对于大部分数据库来说,几个小时或许更合适。我们可以通过测试来保证连接的可靠性。唯一可能需要设置为几分钟或者更短时间的是maxIdleTimeExcessConnections。

配置连接测试

c3p0可以通过多种方式测试连接,以减少应用遇到连接失效的可能性。连接池中的连接可能有多种原因导致失效: 一些JDBC驱动特意设置timeout; 数据库或者网络有时候会挂掉;连接本身可能因为资源泄露,驱动bug或者其他原因失效。

c3p0有多种测试连接的方式

  • automaticTestTable :c3p0会根据传入的名字创建一个空的测试表,通过对这个表的query进行连接测试。并且会忽略prefferredTestQuery(default: null)
  • connectionTesterClassName :ConnectionTester 或者QueryConnectionTester
    的实现类, 用来进行连接测试, 一般不推荐使用 ( Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester
    )
  • preferredTestQuery: 定义用来测试连接的query语句,一般不推荐使用
  • idleConnectionTestPeriod : c3p0会测试所有的闲置但是没有checked-out的连接, 时间间隔为设置的值(default:0 不进行测试)
  • testConnectionOnCheckin: 如果设置为true,在每个连接checkin的时候异步验证连接是否有效(default:false)
  • testConnectionOnCheckout: 如果设置为true,在每个连接checkout的时候验证连接是否有效(default:false)

idleConnectionTestPeriod, testConnectionOnCheckout和testConnectionOnCheckin 决定"何时"测试连接。automaticTestTable, connectionTesterClassName和 preferredTestQuery 决定"怎样"测试连接。

如果使用JDBC4并且c3p0在0.9.5版本以上,建议放手让driver进行连接测试,c3p0会首先尝试使用JDBC4引入的isValid()方法进行测试,这个方法速度快并且可靠。

对于之前的版本c3p0默认在连接关联的DatabaseMetaData上使用getTables()方法,这个方法非常稳定并且适用于不同的数据库,但是比正常的query慢很多,使用它做连接测试可能会严重影响连接池性能。

在老版本中提升连接测试性能的一个简单的办法是使用preferredTestQuery 定义一个测试query。但是需要注意的是,如果在datasource初始化之前query的表不存在的话, preferredTestQuery 会出错导致测试失败。根据数据库或者driver的不同, 像select 1这种的测试语句可能(不)会提高效率。

如果自定义query效率不够好,使用automaticTestTable, c3p0会根据传入的名称建立一个空表来测试连接。

进行连接测试最可靠的时机在check-out, 但是这也最为耗时。大多数应用应该可以通过一起使用idleConnectionTestPeriod和testConnectionOnCheckin进行可靠测试,这两个都是异步的,带来更好的性能。

对有些应用来说, 性能比偶发的数据库异常更为重要。c3p0默认不进行连接测试。设置一个相对长的ideaConnectionTestPeriod, 并不在check-in/out测试则会带来高效的性能。

连接测试建议
  1. 如果你确定driver 支持JDBC4 Connection.isValid()方法,并且使用c3p0-0.9.5以上版本, 不要设置preferredTestQuery。
    如果driver不支持这个方法(或者你不确定), 并且数据库是MySQL或者Postgres, 在preferredTestQuery中使用SELECT 1。
    对于其他数据库,参照这里的一些建议

2.开始直接设置testConnectionOnCheckout=true, 保证程序运行正确和稳定。如果性能让你满意,那就可以保持这个设置了,这是最简单最可靠测试连接的方法。但是它确实有很大的性能开销(客户端可以感知的到)。

3.如果想减少连接检查带来的性能开销:

a. 设置testConnectionOnCheckout为false

b. 设置testConnectionOnCheckin为true

c. 设置idleConnectionTestPeriod 为30(秒),启动程序进行测试。这个是一个很稳定的设置,每30秒所有的连接在check-in的时候都会进行测试。程序应该很少会碰到关闭或者陈旧的连接,并且连接池应该可以从数据库关闭和重启后迅速恢复。但是一直这样测试还是会有一些开销。

d.如果数据库很少进行重启,那么可以考虑增大idleConnectionTestPeriod间隔,比如300,然后测试看看客户端是否会遇到关闭的连接。如果没有,那么定格在300或者可以试更大的数字。然后考虑将testConnectionOnCheckin设置回false来减少check-in检查。反之,如果遇到关闭的连接,可以考虑减少idleConnectionTestPeriod的值,将testConnectionOnCheckin设置回true。

参数的设置取决于对性能和可靠性的权衡,具体的数字并不重要,这里没有一个准确的“最佳值”,而是需要进行测试。

选取2 还是3 取决于客户端在check connection out以后的工作量,如果客户端经常执行复杂查询或者操作,一个很快的连接检查不会有助于整体性能的提升。但是如果客户端check connection out以后的操作很简单,那么附加一个额外的检查会明显拖慢性能。

理论上看起来很美好,但是我们往往很难进行权衡。推荐的做法是测试3,看看是否会提高性能,是否会遇到关闭的连接,在数据库重启的情况下是否能够恢复,再做出决定。

但是一定要保证测试本身的性能,JDBC是否支持isValid, 或者我们是否有一个合适的preferredTestQuery

配置Statement池

c3p0实现了JDBC定义的PreparedStatement的池. 有些时候,使用statement池可以显著提高应用性能。但是有的时候statement池带来的开销可能会轻微影响性能。是否使用,怎么配置取决于数据库的解析,执行计划,和对query语句的优化(对于prepared statement)。不同的数据库和不同的JDBC驱动在这方面表现迥异。将不使用statement池的性能作为基准来测试它可以带来的性能提升是一个不错的方法。

statement池对应的参数有以下几种:

maxStatements 是JDBC中用来控制statement池的标准参数。表示DataSource中最多可以缓存的PreparedStatement的数量。当达到上限的时候,pool会移除LRU(最近最少使用的) statement。这听起来十分简单,但是细想是一个很奇怪的行为。因为被缓存的statements从概念上来说分属各自的连接,并不是全局资源。为了找到一个合适的maxStatements大小,不会"毁掉"被缓存的statements,我们需要考虑经常使用的PreparedStatement的数量,并且需要乘以连接池中连接的数量(连接池很忙的话可能达到maxPoolSize)。

maxStatementsPerConnection是一个非标准的配置参数, 但是看起来更合理一些。 它定义了每个connection允许的PreparedStatement的最大数量。我们可以将这个值设置的比我们应用中的"常用statements"的数量稍微大一些。

上述任何一个参数如果大于0, statement池就会开启。这两个设置是分别生效的,彼此不会影响。

如果statementCacheNumDeferredCloseThreads大于0, statement池会推迟物理关闭缓存的statements的时机,直到它所在的connection不再被使用。在一些JDBC driver中(特别是Oracle), connection在使用的时候是不会关闭它拥有的statement的。这个参数默认值是0,如果发现有和connection 关闭任务相关的"明显的死锁",我们可以尝试设置一个正数,绝大多数情况这个值应该是1。如果需要多余1个线程来做statement销毁的工作,那么 我们可能需要调大maxStatements或者maxStatementsPerConnection, 而不是调大statementCacheNumDeferredCloseThreads。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容