web项目为什么按装到tomcat服务器上过一个星期后就无法连接数据库了?

zhihuaaa 2009-02-19 09:45:21
web项目为什么按装到tomcat服务器上过一个星期后就无法连接数据库了?重起tomcat服务器后就又可以使用了。
代码中数据库的连接每次使用后都关闭了。[
...全文
634 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
东莞IT男 2010-06-12
  • 打赏
  • 举报
回复
是我们开发过程最好的选择:
如果连接取连接会检测物理连接是否断掉,如果断掉,就会在pools remove 断掉了的代理连接.不会挂掉的.(就会象第一种测试那样挂掉的 因为我们设置的maxActive = 3 活动对象最大数是3 ,但它的物理连接都断掉了)
注意 validationQuery 是一定要的;(如果没有,设置testOnBorrow,testOnReturn,testWhileIdle 无效的)
jack420124 2009-02-20
  • 打赏
  • 举报
回复
我上面说得有点不对,因为dbcp 依赖容器,和单独在代码里面不一样的:
如果是在代码里面向下面这样用:
package db;


import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
import java.sql.Statement;
import org.apache.commons.dbcp.BasicDataSource;

public class MySQLConnectionManager
{
private String url = "jdbc:mysql://localhost:3306/db_wis";
private String userName = "root";
private String password = "sa";
private BasicDataSource bds;
public MySQLConnectionManager()
{
bds = new BasicDataSource();
bds.setDriverClassName("org.gjt.mm.mysql.Driver");
bds.setUrl(url);
bds.setUsername(userName);
bds.setPassword(password);
bds.setMaxActive(30);
bds.setDefaultAutoCommit(false);
bds.setMaxWait(10000);
bds.setValidationQuery("select 1");
bds.setTestOnBorrow(true);
bds.setTestOnReturn(true);
bds.setTestWhileIdle(true);

}

void checkConnection()throws Exception
{
Connection connection = bds.getConnection();
System.out.println("connection currentActive = " + bds.getNumActive());

Connection connection1 = bds.getConnection();
System.out.println(" connection1 currentActive = " + bds.getNumActive());
Connection connection2 = bds.getConnection();
System.out.println(" connection2 currentActive = " + bds.getNumActive());

System.out.println(connection.hashCode());
System.out.println(connection1.hashCode());
System.out.println(connection2.hashCode());


connection.close();

Connection aa = bds.getConnection();
System.out.println(aa.hashCode());
aa.close();
connection2.close();
connection1.close();
Thread.currentThread().sleep(1000*15);
Connection testconnection = bds.getConnection();
System.out.println(testconnection.hashCode() + ">>>> " + testconnection.isClosed() + bds.getNumActive());
Statement statement = testconnection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from wis_admin_user");
while(resultSet.next())
{
System.out.println("resultSet.getInt(2) = " + resultSet.getString(2));
}
if(resultSet != null)
resultSet.close();
if(testconnection != null)
testconnection.close();
}

public static void main(String []args)
{
try
{
MySQLConnectionManager connectionManager = new MySQLConnectionManager();
connectionManager.checkConnection();
}catch(Exception ex)
{
ex.printStackTrace();
}
}
}



的话,我上面说的是对的,断掉的物理连接会 pools 会自己remove 断掉的对象.

依赖tomcat 就不一样了:
配置数据库dbcp
我测试过培植如下:
<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" username="root" password="sa" maxActive = "3" maxIdle = "30" maxWait = "10000"
testOnBorrow = "true" testOnReturn = "true" testWhileIdle = "true"
validationQuery = " select 1 "
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/db_wis"/>

</Context>

web.xml
<resource-ref>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

java 代码:


public static void show()
{
javax.sql.DataSource ds = null;
System.out.println(" ------------------- show()");
try{
Context ctx = new InitialContext();
if(ctx == null)
throw new Exception("no Context!");
System.out.print(" >>>>> " + ctx.lookup("java:comp/env/jdbc/TestDB").getClass());
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/TestDB");


}catch(Exception e)
{
System.out.println(e.getMessage());

return;
}
Connection testconnection = null;

try{
testconnection = ds.getConnection();
System.out.println(testconnection.hashCode() + ">>>> " + testconnection.isClosed() );
Statement statement = testconnection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from wis_admin_user");
while(resultSet.next())
{
System.out.println("resultSet.getInt(2) = " + resultSet.getString(2));
}
if(resultSet != null)
resultSet.close();

}catch(Exception ex)
{
ex.printStackTrace();

}
finally
{
try{
if(testconnection != null)
{
if(!testconnection.isClosed())
testconnection.close();
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
测试的:
1:如果是: <Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" username="root" password="sa" maxActive = "3" maxIdle = "30" maxWait = "10000"

driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/db_wis"/>

</Context>
会出错,时间超过了mysql wait_timeout ,interactive_timeout(我设置的是5秒)连接断掉后,它的物理连接断掉了.
pools 里面的连接对象没删除.超过了3个死掉了.更本不行不通.
2:如果是
<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" username="root" password="sa" maxActive = "3" maxIdle = "30" maxWait = "10000"

driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/db_wis?autoReconnect=true"/>

会出错,时间超过了mysql wait_timeout ,interactive_timeout(我设置的是5秒)连接断掉后,它的物理连接断掉了.
pools 里面的连接对象 会出现一次异常,tomcat 会自动去连接,如果在超过 5 秒没用,又会断开,如此下去.(这样的话
在写程序我门要做异常处理,在异常里重新取得连接,照样可以)

3:如果是
<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" username="root" password="sa" maxActive = "3" maxIdle = "30" maxWait = "10000"
testOnBorrow = "true" testOnReturn = "true" testWhileIdle = "true"
validationQuery = " select 1 "
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/db_wis"/>

</Context>
是我们开发过程最好的选择:
如果连接取连接会检测物理连接是否断掉,如果断掉,就会在pools remove 断掉了的代理连接.不会挂掉的.(就会象第一种测试那样挂掉的 因为我们设置的maxActive = 3 活动对象最大数是3 ,但它的物理连接都断掉了)
注意 validationQuery 是一定要的;(如果没有,设置testOnBorrow,testOnReturn,testWhileIdle 无效的)


好了这是我做天下午的总结:也算是动了我一翻脑筋了啊:也算把我心得跟大家分享下,希望对大家开发有所帮助.
如果我总结的是对的.帮我顶下,呵呵.如果分析有漏洞,有错误望大家指点
我的邮箱地址:wxp03@163.com ,QQ:542995961




zhihuaaa 2009-02-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jack420124 的回复:]
你那是数据库连接池是吧,数据库有个默认的时间间隔,如果过了那时间间隔没用,就会自动断掉的.
参数没有配置完全
[/Quote]
1楼:你说的不是没有道理。这个项目已经发布到网上了。每天都有上百人登录。什么都正常。只是过一个来星期,就突然出现这种问题,在重新重起一下服务器也就好了。但总不能每次都要重起服务器吧。请指点。
fabric区块链 2009-02-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jack420124 的回复:]
你那是数据库连接池是吧,数据库有个默认的时间间隔,如果过了那时间间隔没用,就会自动断掉的.
参数没有配置完全
[/Quote]
有道理
jack420124 2009-02-19
  • 打赏
  • 举报
回复
你那是数据库连接池是吧,数据库有个默认的时间间隔,如果过了那时间间隔没用,就会自动断掉的.
参数没有配置完全
jack420124 2009-02-19
  • 打赏
  • 举报
回复
也就是说,你换个新的dbcp 版本,也就没你那问题了
jack420124 2009-02-19
  • 打赏
  • 举报
回复
你这数据库连接池是老版本的dbcp.新的功能有这么个特点,如果数据库引擎与你pools 的connection 连接断开,
或你数据库引擎停止后又启动了,那这样池中的pools 会把断掉的connection 自动remove 掉的,
你换个新的版本dbcp ,后测试下,
测试步骤如下: 你首先写个简单程序创建保证pools 的连接达到maxActive 数字,设个断点
后,停止数据库引擎,在用dabaseSource.getConection取下连接,看有没有提示connection 断开什么样的错误提示就行了

如果有什么问题你,可以联系我QQ:542995961

5,655

社区成员

发帖
与我相关
我的任务
社区描述
Web开发应用服务器相关讨论专区
社区管理员
  • 应用服务器社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧