请教各位高手,数据库连接到底能有多大的资源消耗?
1.如果我每次使用数据库都重新连接一次,会有什么后果(系统会因为重荷而崩溃吗)?
2.在连接数据库的各语句中,哪个消耗系统资源最严重?
Class.forName,
DriverManager.getConnection,
createStatement,
execute
3.我发现如果不及时断开数据库的连接,再次使用数据库就有可能出问题,而Java又没有C++的析构函数(finalize调用的太“不及时”了!),那么,应该如何设计与数据库部分的连接呢?每使用数据库就连接一次可行不可行呢,还有什么好办法解决这个问题?
问题点数:100、回复次数:4Top
1 楼dd777(grass)回复于 2003-02-04 17:06:37 得分 25
1.每次使用数据库都重新连接一次当然不好,如果拥护足够多,系统会死掉。
最好优化一下,不要太多的connection
2.这个我没经验,我想Class.forName,createStatement占用的少;getConnection,execute比较多吧。
3. 这确实是个问题,一般我不会直接在*.jsp中做sql、连接、关闭等操作,
做几个bean,把要作的动作都封起来,在 jsp中可以随时调用,效率会比较高;最好不要每使用数据库就连接一次,尽量优化吧,我尝试过。对于小用户量的系统,没什么区别。
祝好运!
Top
2 楼yysinger(singer)回复于 2003-02-04 17:48:07 得分 25
数据库的连接是占用的资源有两中资源,其一:数据库的连接数,其二:系统的内存资源,但是如果你所做的系统不是很大,访问量也不很大的情况下,不必考虑这个问题,每一次建立一个连接,之后关掉就可以了,因为使用使用数据库连接池还要考虑同步的问题,也是很复杂的Top
3 楼zhirenshao(我属老鼠)回复于 2003-02-04 19:17:42 得分 50
连接数据库是很费时间的一项工作,所以,如果你的每个JSP页面里都有DriverManager.getConnection()这句的话,那你的网站肯定要慢死了(除非你有超快的服务器)。
但是,如果你只建立一个连接,然后所有用户都使用这个连接,那肯定也慢死了,因为所有对数据库的查询和更新操作将一个一个地通过这个唯一的连接,发送到数据库。
比较好而且常用的解决办法有两个。第一个是使用连接池,任何对数据库的查询和存取并不是直接发往数据库,而是发到连接池,连接池可以管理这些对数据库的操作。它可以同时处理大量的对数据库的操作,而不是像只建立一个连接那样,一条一条处理。因为现在的数据库系统都是设计成多线程的,可以同时处理多个连接的。
下面重点来说说第二种方法,就是把数据库连接作为session的一部分。原理很简单。当有一个用户登陆你的网站时,为其新建一个数据库连接,例如
Connection conn = DriverManager.getConnection("");
然后,把它放到session里面
session.setAttribute("servletapp.connection",conn);
于是conn这个对象就不会被销毁,因此此用户对数据库的连接就一直保留着,然后此用户若是在你网站上浏览论坛或者购物,一直都是用这个连接,而不用重新连接数据库,速度也就加快了。 直到他登出这个网站,或者session到期了,那么conn这个对象就会自动被销毁,那么,他对数据库的连接也就断开了。
用这个方法,每个用户可以有其自己的连接,即使若干用户同时发出对数据库的查询或存取,也都是通过其单独的连接,速度当然大大加快了。
在具体实现上,还需要写一个HttpSessionBindingListener,因为,当此用户登出你的网站时,你一定会写
session.invalidate();
于是,所有session里面的对象都销毁,包括conn,可是对数据库的连接还没断开。因此你要写一个class,实现interface HttpSessionBindingListener;实现里面的public void valueBound(HttpSessionBindingEvent event)和public void valueUnbound(HttpSessionBindingEvent event)
当一个对象被绑定到session里面去时,valueBound()会自动被调用,当一个对象被session删掉或者session被销毁时,valueUnbound()会自动被调用。所以,你可以把断开数据库的语句放在valueUnbound()里面。例如
public void valueUnbound(HttpSessionBindingEvent event) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {}
}
这样,当你的用户登出网站时,以上函数被调用,然后conn与数据库服务器断开。
下面是〈Java Servlet Programming〉里面的一个完整例子
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
class ConnectionHolder implements HttpSessionBindingListener {
private Connection con = null;
public ConnectionHolder(Connection con) {
// Save the Connection
this.con = con;
try {
con.setAutoCommit(false); // transactions can extend between web pages!
}
catch(SQLException e) {
// Perform error handling
}
}
public Connection getConnection() {
return con; // return the cargo
}
public void valueBound(HttpSessionBindingEvent event) {
// Do nothing when added to a Session
}
public void valueUnbound(HttpSessionBindingEvent event) {
// Roll back changes when removed from a Session
// (or when the Session expires)
try {
if (con != null) {
con.rollback(); // abandon any uncomitted data
con.close();
}
}
catch (SQLException e) {
// Report it
}
}
}
/* Actual Servlet */
public class ConnectionPerClient extends HttpServlet {
public void init() throws ServletException {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e) {
throw new UnavailableException("Couldn't load OracleDriver");
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
HttpSession session = req.getSession(true);
Connection con;
// Synchronize: Without this two holders might be created for one client
synchronized (session) {
// Try getting the connection holder for this client
ConnectionHolder holder =
(ConnectionHolder) session.getAttribute("servletapp.connection");
// Create (and store) a new connection and holder if necessary
if (holder == null) {
try {
holder = new ConnectionHolder(DriverManager.getConnection(
"jdbc:oracle:oci7:ordersdb", "user", "passwd"));
session.setAttribute("servletapp.connection", holder);
}
catch (SQLException e) {
log("Couldn't get db connection", e);
}
}
// Get the actual connection from the holder
con = holder.getConnection();
}
// Now use the connection
try {
Statement stmt = con.createStatement();
stmt.executeUpdate(
"UPDATE INVENTORY SET STOCK = (STOCK - 10) WHERE PRODUCTID = 7");
stmt.executeUpdate(
"UPDATE SHIPPING SET SHIPPED = (SHIPPED + 10) WHERE PRODUCTID = 7");
// Charge the credit card and commit the transaction in another servlet
res.sendRedirect(res.encodeRedirectURL(
req.getContextPath() + "/servlet/CreditCardHandler"));
}
catch (Exception e) {
// Any error is grounds for rollback
try {
con.rollback();
session.removeAttribute("servletapp.connection");
}
catch (Exception ignored) { }
out.println("Order failed. Please contact technical support.");
}
}
}
Top
4 楼princerock(princeVC)回复于 2003-02-04 19:57:53 得分 0
upTop




