我正在使用遺留代碼,並且由於我們有主要的數據庫連接問題(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);
它是安全的假設,我們不與我們正在使用的數據庫保持一致?
由於每個人都在這方面工作已經沒有了,我怎麼弄清楚爲什麼有人會使用另一個,如果我應該考慮刪除一個可能?
我該如何去尋找是否有東西在這裏造成泄漏?
關於如何解決這個問題的任何建議?
您應該使用類似Apache JDBC的連接池。除非由於某些原因不能使用外部庫,否則試圖重新發明輪子是毫無意義的。 – TameHog