数据库连接池为什么要建立多个连接

一般程序在访问数据库的时候,都是使用数据库连接池,比如:DBCP,C3P0等等。至于为什么使用连接池,大家都知道,就是为了避免频繁的与数据库建立连接,
因为建立连接是一个比较耗时的操作。而连接池的配置基本差不多,都会设置一个最大连接数。
现在就有一个疑问,为什么最大连接数要设置成多个?只建立1个连接,一直都不关闭可以吗?1个的话岂不是占用系统资源更少吗(排除掉使用transaction的情况,因为transaction的提交和回滚是在Connection上的)?难道说java.sql.Connection不是线程安全的?


http://docs.oracle.com/javase/1.3/docs/guide/jdbc/spec/jdbc-spec.frame9.html
9.2     Multi-threading
We require that all operations on all the java.sql objects be multi-thread safe and 
able to cope correctly with having several threads simultaneously calling the same object.
Some drivers may allow more concurrent execution than others. 
Developers can assume fully concurrent execution; 
if the driver requires some form of synchronization, it will provide it. 
The only difference visible to the developer will be that applications will run with reduced concurrency.
For example, two Statements on the same Connection can be executed concurrently and their ResultSets can be processed concurrently 
(from the perspective of the developer). Some drivers will provide this full concurrency. Others may execute one statement and wait until it completes before sending the next.
One specific use of multi-threading is to cancel a long running statement. This is done by using one thread to execute the statement and another to cancel it with its Statement.cancel() method.
In practice we expect that most of the JDBC objects will only be accessed in a single threaded way. However some multi-thread support is necessary, 
and our attempts in previous drafts to specify some classes as MT safe and some as MT unsafe appeared to be adding more confusion than light. 
也就是说,java.sql.Connection是线程安全的,应用程序可以并发的使用同一个Connection来访问数据库,问题是,数据库的驱动可能会是并发的处理请求,也可能是串行的处理,这取决于数据库厂商。同时也说了,实际开发中最好还是单线程方式使用。


http://docs.oracle.com/cd/B14117_01/java.101/b10979/tips.htm#i1005436
The Oracle JDBC drivers provide full support for programs that use Java multithreading. 
The following example creates a specified number of threads and lets you determine whether or not the threads will share a connection. 
If you choose to share the connection, then the same JDBC connection object will be used by all threads (each thread will have its own statement object, however).


Because all Oracle JDBC API methods are synchronized, if two threads try to use the connection object simultaneously, 
then one will be forced to wait until the other one finishes its use.
Oracle的JDBC API都是synchronized的,因此,对数据库的操作肯定是串行的。


http://forums.mysql.com/read.php?39,171022,171195#msg-171195
While you _can_ share a connection across threads (especially if each thread has its own Statement), it's usually not a good idea. 
The JDBC API is not really designed to be used in a thread-safe way, and most JDBC connections (including MySQL's) can only process a single query at a time.
You'll be adding _more_ contention in your system rather than concurrency compared to just giving each thread a "private" connection. 
MySQL的Connection也是串行的执行数据库操作的。




http://stackoverflow.com/questions/9428573/is-it-safe-to-use-a-static-java-sql-connection-instance-in-a-multithreaded-syste
This way the connection going to be shared among all requests sent by all users and thus all queries will interfere with each other. 
But threadsafety is not your only problem, resource leaking is also your other problem. 
You're keeping a single connection open during the entire application's lifetime. 
The average database will reclaim the connection whenever it's been open for too long which is usually between 30 minutes and 8 hours, depending on DB's configuration. 
So if your web application runs longer than that, the connection is lost and you won't be able to execute queries anymore.
这个就是说,用1个连接可能会出现长时间不用试导致连接被回收的情况。一般连接的最大不活动时间在30分钟到8个小时之间,取决于数据库服务器的配置。




设置Mysql的连接超时参数
http://blog.chinaunix.net/uid-26758020-id-3307042.html
在Mysql的默认设置中,如果一个数据库连接超过8小时没有使用(闲置8小时,即28800s),mysql server将主动断开这条连接,后续在该连接上进行的查询操作都将失败,
将出现:error 2006 (MySQL server has gone away)!。
查看mysql server超时时间:
msyql> show global variables like '%timeout%';
设置mysql server超时时间(以秒为单位): 
msyql> set global wait_timeout=10;
msyql> set global interactive_timeout=10;
ps:我们的线上服务器设置的是2个小时。


MySQL中的配置参数interactive_timeout和wait_timeout(可能导致过多sleep进程的两个参数)
http://www.cnblogs.com/jiunadianshi/articles/2475475.html
1)interactive_timeout:
参数含义:服务器关闭“交互式连接”前等待活动的秒数。交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。
参数默认值:28800秒(8小时)
(2)wait_timeout:
参数含义:服务器关闭“非交互连接”之前等待活动的秒数。
在线程启动时,根据全局wait_timeout值或全局interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义)。
参数默认值:28800秒(8小时)
MySQL服务器所支持的最大连接数是有上限的,因为每个连接的建立都会消耗内存,因此我们希望客户端在连接到MySQL Server处理完相应的操作后,应该断开连接并释放占用的内存。如果你的MySQL Server有大量的闲置连接,他们不仅会白白消耗内存,而且如果连接一直在累加而不断开,最终肯定会达到MySQL Server的连接上限数,这会报'too many connections'的错误。对于wait_timeout的值设定,应该根据系统的运行情况来判断。在系统运行一段时间后,可以通过show processlist命令查看当前系统的连接状态,如果发现有大量的sleep状态的连接进程,则说明该参数设置的过大,可以进行适当的调整小些。
问题:
如果在配置文件my.cnf中只设置参数wait_timeout=100,则重启服务器后进入,执行:
Mysql> show variables like “%timeout%”;
会发现参数设置并未生效,仍然为28800(即默认的8个小时)。
查询资料后,要同时设置interactive_timeout和wait_timeout才会生效。
【mysqld】
wait_timeout=100
interactive_timeout=100
重启MySQL Server进入后,查看设置已经生效。


http://blog.csdn.net/z1988316/article/details/7976038
问题1:这里为什么要同时设置interactive_timeout,wait_timeout的设置才会生效?
答:    不设置interactive_timeout,wait_timeout也会生效。
问题2:interactive的值如果设置的和wait_timeout不同,为什么Interactive_timeout会覆盖wait_timeout?
答:在交互模式下(CLIENT_INTERACTIVE),interactive_timeout才生效,非交互模式下,不生效。
问题3:在进行MySQL优化时,因为interactive_timeout决定的是交互连接的时间长短,而wait_timeout决定的是非交互连接的时间长短。如果在进行连接配置时mysql_real_connect()最后一个参数client_flag不设置为CLIENT_INTERACTIVE,是不是interactive_timeout的值不会覆盖wait_timeout?
答:可以做实验试试。
问题4:为了减少长连接的数量,在设置优化时是不是可以将interactive_timeout的值设置的大些,而wait_timeout的值设置的小些?但是问题2的描述好像又不允许这样。。。
答:如2所述,在交互模式下,interactive_timeout取代wait_timeout。这样,如果有的客户端是交互模式方式连接mysql server。那么客户端的timeout受制于interactive_timeout。如果有的客户端是非交互模式,长连接mysql server。那么客户端的timeout受制于wait_timeout。(是否是交互模式的连接,由客户端决定)


总结一下:
(1)jdk的规范里面说了,对于客户端来说Connection是线程安全的,允许多线程并发的使用,但是,数据库驱动可能是并行的执行,也可能是串行的执行SQL。
(2)同一个connection,Oracle和MySQL的驱动都是串行的执行操作,因此公用一个Connection与使用多个Connection相比会降低并发度,这应该才是最主要的原因。
(3)数据库一般都会有一个最大不活动时间,超过这个时间就会把连接关闭掉,因此,只有一个Connection的话,会出现连接已关闭,需要重建的情况。(其实这个倒不是啥大问题,启动一个后台线程,隔一段时间就执行一次查询,保持住连接不关闭就可以了。)
(4)到底多少个连接合适,这是个问题。如果连接数过多,显然是浪费,而且,数据库对每个user支持的连接数都是有限制的。如果连接数少,考虑突发访问量变大的情况,肯定就会出现有的线程取不到连接的情况,这个请求就会失败。如果多个请求可以共用连接,这个时候至少不会出现获取不到连接直接失败,顶多是处理的时间变长了。

你可能感兴趣的:(java)