2016-02-20 46 views
0

我正在使用遺留代碼,並且由於我們有主要的數據庫連接問題(1000+ sleeping connections at all times)和如此慢的返回結果,我決定深入研究我們所謂的'Database Pooling'體系結構。數據庫連接池在整個代碼中使用不正確

顯然我們有兩個Database.java和2 ConnectionPool.java,一對在Web應用程序模塊中,另一對在數據庫模塊中。

所以它看起來像這樣:

package mil.dlas.database; 

    Database.java 
    ConnectionPool.java 

package ti.dlas; 
    Database.java 
    ConnectionPool.java 

包ti.dlas

public synchronized void getConn(ErrorBean myError) 
{ 
    try 
    { 
     try 
     { 
      if (this.webBasedConnection) 
      { 
       if(dataSource == null) 
       { 
        dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/mydb"); 
       } 

       if(dataSource == null) 
       { 
        dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/mydb"); 
       } 

       conn = dataSource.getConnection(); 
      } 
      else 
      { 
       getConnInterfaceBased(myError); 
      } 
     } 
     catch (NamingException e) 
     { 
      e.printStackTrace(); 
      getConnInterfaceBased(myError); 
     } 
     catch(SQLException e) 
     { 
      e.printStackTrace(); 
      getConnInterfaceBased(myError); 
     } 
    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
     getConnInterfaceBased(myError); 
    } 
} 
public synchronized void insertOrUpdatePS(String query,Object[] param, ErrorBean eb) 
{ 
     java.sql.PreparedStatement pStat = null; 
     try 
     {   
      getConn(eb); 
      pStat = conn.prepareStatement(query); 

      for(int i=0; i<param.length;i++) 
      { 
       pStat.setObject(i+1,param[i]); 
      } 
      iRowsUpdated = pStat.executeUpdate(); 
     } 
     catch(SQLException e) 
     {e.printStackTrace();} 
     catch(Exception e) 
     {e.printStackTrace();} 
     finally { 
      if(pStat!=null)    
       try {pStat.close();} 
       catch(SQLException e){}    
      returnConn(); 
     } 
} 
/**ConnectionPool .java**/ 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.SQLException; 
import java.util.Vector; 

public class ConnectionPool implements Runnable, java.io.Serializable{ 
    private String driver, url, username, password; 
    private int maxConnections; 
    private boolean waitIfBusy; 
    private Vector availableConnections, busyConnections; 
    private boolean connectionPending = false; 

    public ConnectionPool(String driver, String url, 
         String username, String password, 
         int initialConnections, 
         int maxConnections, 
         boolean waitIfBusy) 
     throws SQLException { 
    this.driver = driver; 
    this.url = url; 
    this.username = username; 
    this.password = password; 
    this.maxConnections = maxConnections; 
    this.waitIfBusy = waitIfBusy; 
    if (initialConnections > maxConnections) { 
     initialConnections = maxConnections; 
    } 
    availableConnections = new Vector(initialConnections); 
    busyConnections = new Vector(); 
    for(int i=0; i<initialConnections; i++) { 
     availableConnections.addElement(makeNewConnection()); 
    } 
    } 

    public synchronized Connection getConnection() 
     throws SQLException { 
    if (!availableConnections.isEmpty()) { 
     Connection existingConnection = 
     (Connection)availableConnections.lastElement(); 
     int lastIndex = availableConnections.size() - 1; 
     availableConnections.removeElementAt(lastIndex); 

     if (existingConnection.isClosed()) { 
     notifyAll(); 
     return(getConnection()); 
     } else { 
     busyConnections.addElement(existingConnection); 
     return(existingConnection); 
     } 
    } else { 
     if ((totalConnections() < maxConnections) && 
      !connectionPending) { 
     makeBackgroundConnection(); 
     } else if (!waitIfBusy) { 
     throw new SQLException("Connection limit reached"); 
     } 

     try { 
     wait(); 
     } catch(InterruptedException ie) {} 
     return(getConnection()); 
    } 
    } 

    private void makeBackgroundConnection() { 
    connectionPending = true; 
    try { 
     Thread connectThread = new Thread(this); 
     connectThread.start(); 
    } catch(OutOfMemoryError oome) {} 
    } 

    public void run() { 
    try { 
     Connection connection = makeNewConnection(); 
     synchronized(this) { 
     availableConnections.addElement(connection); 
     connectionPending = false; 
     notifyAll(); 
     } 
    } catch(Exception e) { } 
    } 

    private Connection makeNewConnection() 
     throws SQLException { 
    try { 
     Class.forName(driver); 
     Connection connection = 
     DriverManager.getConnection(url, username, password); 
     return(connection); 
    } catch(ClassNotFoundException cnfe) { 
     throw new SQLException("Can't find class for driver: " + 
          driver); 
    } 
    } 

    public synchronized void free(Connection connection) { 
    busyConnections.removeElement(connection); 
    availableConnections.addElement(connection); 
    notifyAll(); 
    } 

    public synchronized int totalConnections() { 
    return(availableConnections.size() + 
      busyConnections.size()); 
    } 
} 

包mil.dlas.database;

public synchronized void getConn() 
{ 
    try 
    { 
     try 
     { 
      if(dataSource == null) 
      { 
       dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/mydb"); 
      } 
      conn = dataSource.getConnection(); 
      webBasedConnection = true; 
     } 
     catch (NamingException e){getConnInterfaceBased} 
     catch(SQLException e){getConnInterfaceBased();} 
    } 
    catch(Exception ex){getConnInterfaceBased();} 
}  
public synchronized void insertOrUpdatePS(String query, Object[] param) 
{ 
    java.sql.PreparedStatement pStat = null; 
    String jobnumber = ""; 

    try 
    { 
     getConn(); 
     if(!webBasedConnection) 
      conn = checkOut(); 

     pStat = conn.prepareStatement(query); 

     for(int i=0; i<param.length;i++) 
     { 
      if (i==0) 
       jobnumber = param[i].toString(); 

      pStat.setObject(i+1,param[i]); 
     } 

     int insertUpdateReturnCode = pStat.executeUpdate(); 
     ResultSet rs = pStat.getGeneratedKeys(); 
     if (rs.next()) 
     { 
      ResultSetMetaData rsmd = rs.getMetaData(); 
      int colCount = rsmd.getColumnCount(); 
      String columnOneName = rsmd.getColumnName(1); 

      for (int x = 1; x <= colCount; x++) 
      { 
       String key = rs.getString(x); 
       this.autoIncrementedID = key; 
      } 
     } 
     else 
     { 
      this.autoIncrementedID = ""; 
     } 

    } 
    catch(SQLException e){e.printStackTrace();} 
    catch(Exception e){e.printStackTrace();} 
    finally 
    { 
     if(pStat!=null)    
      try {pStat.close();} 
      catch(SQLException e){}    
     if(this.webBasedConnection) 
      returnConn(); 
     else 
      checkIn(conn); 
    } 
} 
package mil.dlas.database; 

import java.util.*; 
import java.sql.*; 
public class ConnectionPool implements Runnable 
{  
    private int m_InitialConnectionCount = 3; 
    private Vector m_AvailableConnections = new Vector(); 
    private Vector m_UsedConnections = new Vector(); 
    private String m_URLString = null; 
    private String m_UserName = null;  
    private String m_Password = null; 
    private Thread m_CleanupThread = null; 

    protected ConnectionPool(String urlString, String user, String passwd) throws SQLException 
    { 
     m_URLString = urlString; 
     m_UserName = user; 
     m_Password = passwd; 

     for(int cnt=0; cnt<m_InitialConnectionCount; cnt++) 
     { 
      m_AvailableConnections.addElement(getConnection()); 
     }   
     m_CleanupThread = new Thread(this); 
     m_CleanupThread.start(); 
    }  

    private Connection getConnection() throws SQLException 
    { 
     return DriverManager.getConnection(m_URLString, m_UserName, m_Password); 
    } 

    public synchronized Connection checkout() throws SQLException 
    { 
     Connection newConnxn = null; 
     if(m_AvailableConnections.size() == 0) 
     { 
      newConnxn = getConnection(); 
      m_UsedConnections.addElement(newConnxn); 
     } 
     else 
     { 
      newConnxn = (Connection)m_AvailableConnections.lastElement(); 
      m_AvailableConnections.removeElement(newConnxn); 
      m_UsedConnections.addElement(newConnxn); 
     }   
     return newConnxn; 
    } 


    public synchronized void checkin(Connection c) 
    { 
     if(c != null) 
     { 
      m_UsedConnections.removeElement(c); 
      m_AvailableConnections.addElement(c);   
     } 
    }    

    public int availableCount() 
    { 
     return m_AvailableConnections.size(); 
    } 

    public void run() 
    { 
     Connection c = null; 
     try { 
      while(true) 
      { 
       synchronized(this) 
       { 
        while(m_AvailableConnections.size() > m_InitialConnectionCount) 
        { 
         c = (Connection)m_AvailableConnections.lastElement(); 
         m_AvailableConnections.removeElement(c); 
        } 
       }     
       Thread.sleep(60000 * 1); 
      }  
     } 
     catch(Exception e) { e.printStackTrace(); } 
     finally { 
      try{if (c != null) c.close();} 
      catch(SQLException sqle) { sqle.printStackTrace(); } 
     } 
    } 

    public void closeConns() throws SQLException 
    { 
     try { 
      for(int cnt=0; cnt<=m_AvailableConnections.size(); cnt++) 
      { 
       Connection c = (Connection)m_AvailableConnections.lastElement(); 
       c.close(); 
       m_AvailableConnections.removeElement(c); 
      } 
     } 
     catch(Exception e) { e.printStackTrace(); } 
    } 
} 

Throughtout的代碼,我看到這兩個類的呼叫:

Database db = new Database(); 
db.insertOrUpdatePS(qstring.toString(), param); 

Database dbAddMember = (Database) ssb.getObject("db"); 
dbAddMember.insertOrUpdatePS(qstring, param, eb); 

它是安全的假設,我們不與我們正在使用的數據庫保持一致?

由於每個人都在這方面工作已經沒有了,我怎麼弄清楚爲什麼有人會使用另一個,如果我應該考慮刪除一個可能?

我該如何去尋找是否有東西在這裏造成泄漏?

關於如何解決這個問題的任何建議?

+1

您應該使用類似Apache JDBC的連接池。除非由於某些原因不能使用外部庫,否則試圖重新發明輪子是毫無意義的。 – TameHog

回答

1

老實說,代碼是非常可怕的。不是因爲你有自定義的數據庫連接處理,而是因爲遺留代碼正在同步獲取數據庫訪問的方法,這意味着一次只能執行一條SQL語句,這並不好。

你一定不能責怪遺留代碼attempting連接池的解決方案,但在這個時代,你可以安全地假設有任何事情定製編寫很多年前更好和成熟的解決方案。

很多用戶都會對提供給完成任務的best庫自己的意見,但我會說我有很好的成功,在幾個項目中使用:

JTDS一個很好的數據庫驅動程序(http://jtds.sourceforge.net/

Atomikos公司的事務管理(http://www.atomikos.com/Documentation/WebHome

DBCP連接池(https://commons.apache.org/proper/commons-dbcp/

有許多好多其它的。無論如何,從我看到的情況來看,你一定會看到在決定用經過驗證的真正庫替換自定義代碼來完成工作的改進。

相關問題