開発中、一般的な追加、削除、変更、検索などの操作を実行する必要があることがよくありますが、データ量が少ない場合は、直接実行できます。ただし、データ量が増加すると、データベースの接続と解放にそれぞれ一定の時間がかかります。このとき、データベース接続プールを使用してデータベース リンクを維持し、接続のオーバーヘッドを減らすことができます。データベースをプログラム上で管理し、データベースへの負荷を軽減します。その後、データベース接続プールとはどのようなものですか?名前が示すように、池に置かれているのはデータベースへのリンクです。たとえば、魚を食べたい場合は、魚を飼育することができます。自分で稚魚を買ったり育てたりする必要はありません。データベースへのリンクを保存するために使用されます。使用後はそこから直接リンクを取得できます。これを使用するので、コードを自分で記述する必要はありません。オープン ソース接続プールには、c3p0、dbcp、proxool の 3 つがあります。 c3p0 と proxool は使用したことがありません。単純に dbcp プールを使用したことがあります。ここでは、dbcp データベース接続プールの使用方法と、使用時に遭遇するいくつかの落とし穴について説明します
図 1、接続プールを使用する前
図 2 接続プールの使用後の使用
上の図 1 に示すように、接続プールを使用する前に、毎回データベースへのリンクを確立し、量が増えたらいつでも解放する必要があります。データが大きく、データベースへの接続に多くのオーバーヘッドが必要であり、データベースへのアクセスと解放が頻繁に行われると、データベースに大きな負荷がかかります。図 2 は、データベース接続プールを使用した後にすべてのリンクが配置されることを示しています。使用すると、プールから直接取り出され、リンクが切断された場合はプールに戻されます。接続が十分でない場合、後続のユーザーは待つ必要があります。 2. tomcat-dbcp を使用します。jar パッケージ
3. 使用される構成
dbname.Driver=com.mysql.jdbc.Driver dbname.Url=jdbc:mysql://<your ip>/<your dbname>?useUnicode=true&characterEncoding=UTF-8 &autoReconnect=true&failOverReadOnly=false&maxReconnects=10&autoReconnectForPools=true&zeroDateTimeBehavior=convertToNull&connectTimeout=3000 dbname.Username=<your username> dbname.Password=<your password> dbname.InitialSize=15 dbname.MinIdle=10 dbname.MaxIdle=20 dbname.MaxWait=5000 dbname.MaxActive=20 dbname.validationQuery=select 1
ここで、ドライバー、URL、ユーザー名、パスワードは一般的なデータベース接続構成です
InitialSize为初始化建立的连接数
minidle为数据库连接池中保持的最少的空闲的链接数
maxidle数据库连接池中保持的最大的连接数
maxwait等待数据库连接池分配连接的最长时间,超出之后报错
maxactivite最大的活动链接数,如果是多线程可以设置为超出多线程个数个链接数
<pre name="code" class="java">validationQuery测试是否连接是有效的sql语句
public abstract class DB { private static HashMap<String, DataSource> dsTable = new HashMap<String, DataSource>();//此处记得用static private BasicDataSource ds; private PreparedStatement stmt = null; private DataSource getDataSource(String n) { if (dsTable.containsKey(n)) { return dsTable.get(n);//如果不同的数据库,多个连接池 } else { synchronized (dsTable) { ds = new BasicDataSource(); ds.setDriverClassName(DBConfig.getString("db", n.concat(".Driver")));//将<yourname>.properties的值读进来 ds.setUrl(DBConfig.getString("db", n.concat(".Url"))); ds.setUsername(DBConfig.getString("db", n.concat(".Username"))); ds.setPassword(DBConfig.getString("db", n.concat(".Password"))); ds.setInitialSize(DBConfig.getInteger("db", n.concat(".InitialSize"))); ds.setMinIdle(DBConfig.getInteger("db", n.concat(".MinIdle"))); ds.setMaxIdle(DBConfig.getInteger("db", n.concat(".MaxIdle"))); ds.setMaxWait(DBConfig.getInteger("db", n.concat(".MaxWait"))); ds.setMaxActive(DBConfig.getInteger("db", n.concat(".MaxActive"))); ds.setValidationQuery(DBConfig.getString("db", n.concat(".validationQuery"))); dsTable.put(n, ds); return ds; } } } protected Connection conn; public boolean open() throws SQLException { BasicDataSource bds=(BasicDataSource)this.getDataSource(this.getConnectionName()); System.out.println("connection_number:"+bds.getNumActive()+"dsTable:"+dsTable); this.conn = this.getDataSource(this.getConnectionName()).getConnection(); return true; } public void close() throws SQLException { if (this.conn != null) this.conn.close(); } protected abstract String getConnectionName();//此函数可以根据自己的需求,将数据库的名字传进来即可 public void prepareStatement(String sql) throws SQLException { this.stmt = this.conn.prepareStatement(sql); } public void setObject(int index, Object value, int type) throws SQLException { this.stmt.setObject(index, value, type); } public void setObject(int index, Object value) throws SQLException { this.stmt.setObject(index, value); } public int execute() throws SQLException { return this.stmt.executeUpdate(); } }
1. 空のデータベースを作成し、リンク数を確認します
プロセスIDを取得します
ps aux|grep <your java name>
リンクされたデータベースへのリンクを表示します
netstat -apn|grep <your processid>
詳細を確認できます 接続プールが正しいかどうかを確認するためにリンクの数が使用されます
マルチスレッド形式で使用されるため、最も重要な落とし穴が発生します。静的の使用法についてあまり詳しくないので、静的を使用しませんでした。その結果、各スレッドがデータベース接続プールを確立し、「開いているファイルが多すぎます」エラーが発生しました。これは、静的が使用されていないためです。スレッドプールが原因です。