では、ページナビゲーション
- 1.どのように接続プールをオープンするのですか?
- 2.関連していると、それが何であるか、接続プール?
- 3.どのように異なるデータベースにアクセスするために同じ接続プールを使用するには?
- 4.デフォルトの最大値と最小接続プールデータベース
「我々が話を聞いたり使用しているデータベース接続プールには、本当にそれがどのくらいのを理解できますか?
- どのようにデータ接続プーリングが有効になっていますか?主なパラメータは何ですか?
- なぜ接続プーリングを使用できますか?
- どのように接続プールに近いですか?
- どのように新しい状況の下で、現在開いているデータベース接続プールを変更しませんか?
- ライフサイクル接続プール?
- データベースサーバが接続を閉じることを余儀なくされている場合はどうなりますか?
================================================== =========================
まず、テスト環境を説明します。
データベースのバージョン:SQLサーバー12.0.2269.0 [のMicrosoft SQL Server 2014のEnterprise(64ビット)]
C#バージョン:マイクロソフトのVisual C#の2015 14.0.25431
クライアントバージョン:4.0.0 System.Data
================================================== =========================
最初のテストへの容易なデータベース・アクセス・クラスを作成します:
パブリック クラスDbAccepter { /// <まとめ> /// データベース接続 /// </要約> プライベート SqlConnectionの_conn = 新しい新しいSqlConnectionオブジェクト(); /// <まとめ> /// 接続ストリング /// </要約> プライベート文字列_connectionString = "" ; /// <要約> /// 接続ストリング /// </要約> パブリック 列のConnectionString { GET { 戻り_connectionStringを; } セット { _connectionString = 値。 _conn.ConnectionString = _connectionString。 } } パブリックデータテーブルのGetData(文字列SQL) { ストリング SSS = _conn.State.ToString()。 使用(SqlCommandオブジェクトCMD = 新しいSqlCommandオブジェクト(SQL、_conn)) { 使用(SqlDataAdapterオブジェクトアダプタ= 新しいSqlDataAdapterオブジェクト(CMD)) { データセットDS = 新しいですデータセット()。 _conn.Open()。 adapter.Fill(DS)。 _conn.Close()。 戻り ds.Tables [ 0 ]。 } } } }
1.どのように接続プールをオープンするのですか?
唯一の接続文字列をオプションに追加することができます。
プライベート 静的な文字列_connectionString = " プーリング=真;接続寿命= 5;最大プールサイズ= 4;プールサイズ= 2分
のデータソース= 127.0.0.1;初期カタログ=のtempdb;ユーザーID =テスト;パスワード= Sm5lAXQiZ10L " ;
内側と接続プールに関連するパラメータに注意してください:
プーリング= TRUE; - オープン接続のプールを表す(デフォルトではオープン)
最小プールサイズ= 2 - 最小接続プール・サイズ:初期接続が最初のn個の接続およびデータベース・サービスを確立されたときに何も実行されないこと
最大プールサイズ= 4 - 最大接続プール・サイズ:必要なときに接続確立の最大数は、確立されています。
例示:プール・サイズ= 2分;最大プールサイズ= 4。
スクリプトの実行]ボタンをクリックすると、次のデータベースを呼び出します。
試す { info.Clear()。 以下のために(int型 i = 0 ; iはnum.Value <; iは++を) { スレッド番目 = 新しいスレッド(GetCurrentDbName)。 th.Start(); } } キャッチ(例外例) { listboxAdd(ex.Message)。 }
ここGetCurrentDbNameは約3秒のようにSQL時、データベース接続し、データベースの現在の名前を取得し、3Sを遅らせるSQLスクリプトの実装を作成することです各実行
SELECT DB_NAME (); WAITFOR遅延' 0時00分03秒' ; - (3秒)
ここでは、最初の接続が最初に確立されたときに2つの接続を作成し、1に設定し、同時。
あなたは、データベース内で見ることができます。
ホスト名=「XXX」とloginameに=「テスト」にsysprocessesから選択*
2.関連していると、それが何であるか、接続プール?
同じプロセスで、とのみ、接続文字列、それは同じ接続プールを使用する限り、接続文字列について。
ここでは、図(最小限のデータプールを変更)に文字列を接続します。
命令の実行後は、その後、データベース接続情報を見てみましょう。
私たちは、それはあなたが同じ接続プールが使用されていないことを疑うことができ、接続情報をよりになりました。あなたは、同時4の数を変更することができます。
接続文字列は、4つを占め修正、2を占めている前に、接続の数が、6になったときに、見ることができます。接続プールのサイズは4に限られているので、その説明は、実際に二つの接続プールを使用することです。
私たちが尋ねるとき、同時接続プールの数は、何が起こるかの最大数よりも大きいですか?ここでは、呼び出し元のスレッドの実行方法を記録する時間を開始および終了、前のプログラムコードを変更します
実行期限スレッド9は、4つ前の4泊3Sの中央について、最初の4つの実質的に同一の期限を見ることができます。3Sよりも最後の4つの中間以降。
説明接続プールのリソースを取得するために4つのスレッドのデータベース要求を開始し、他の人が待ちます。
4つの完全な実行スレッドの後、接続プールのリソースの別の4つのスレッドを獲得し、そして最後に再び真の接続プールを待っているスレッドをリリースします。
その後、我々は、データベースへの接続の数を見て、まだ4です。並行してリクエストの説明複数の、接続プールは、部分が待機する超えます。どのくらいの時間がタイムアウトを待つのだろうか???
結論では、接続プールを使用する場合、あなたは(私は完全にテストされていなかった)書かれたとおりに、同じ接続文字列を使用する必要があります。
3.どのように異なるデータベースにアクセスするために同じ接続プールを使用するには?
実際の開発では、我々は、同じサーバで複数のデータベースにアクセスしますが、あまりにも多くの接続を作成する必要はありません。あなたが別のライブラリが異なる接続文字列を使用して訪問する場合は、複数の接続プールを作成します。
このような:
pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = master; User ID = test; Password=Sm5lAXQiZ10L
这时有两个办法:
1.在SQL语句中指定数据库名称(不太靠谱)
2.不要重新创建连接,而是使用的相同的连接字符串创建连接后再切换数据库。实现代码如下:
using (SqlCommand cmd = new SqlCommand(sql, _conn)) { using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { DataSet ds = new DataSet(); _conn.Open(); //这时指向的是tempdb _conn.ChangeDatabase("master"); //切换数据库 adapter.Fill(ds); _conn.Close(); return ds.Tables[0]; } }
页内导航
- 1.如何开启连接池?
- 2. 那连接池是和什么有关呢?
- 3.如何使用相同的连接池访问不同的数据库?
- 4.数据库连接池的默认最大和最小值
‘关于数据库连接池大家都听说过或者用过,但真正的了解有多少呢?
- 数据连接池如何启用?有哪些主要的参数?
- 为什么要使用连接池?
- 如何关闭连接池?
- 如何在不开启新的连接池情况下切换当前数据库?
- 连接池的生命周期?
- 当数据库服务器强制关闭连接时会怎么样?
===========================================================================
首先说明一下测试环境:
数据库版本:SQL SERVER 12.0.2269.0 [Microsoft SQL Server 2014 Enterprise (64-bit)]
C#版本: Microsoft Visual C# 2015 14.0.25431
客户端版本:System.Data 4.0.0
===========================================================================
首先创建一个数据库访问类,便于测试:
public class DbAccepter { /// <summary> /// 数据库连接 /// </summary> private SqlConnection _conn = new SqlConnection(); /// <summary> /// 数据库连接字符串 /// </summary> private String _connectionString = ""; /// <summary> /// 数据库连接字符串 /// </summary> public string ConnectionString { get { return _connectionString; } set { _connectionString = value; _conn.ConnectionString = _connectionString; } } public DataTable GetData(string sql) { string sss = _conn.State.ToString(); using (SqlCommand cmd = new SqlCommand(sql, _conn)) { using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { DataSet ds = new DataSet(); _conn.Open(); adapter.Fill(ds); _conn.Close(); return ds.Tables[0]; } } } }
1.如何开启连接池?
只需要连接字符串中加入对应的选项即可:
private static String _connectionString = "pooling=true;connection lifetime=5;min pool size = 2;max pool size=4;
Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L";
注意里面和连接池有关的参数:
pooling=true; --表示开启连接池(默认为开启)
min pool size = 2 --最小连接池大小:即什么也没执行初次连接的时候先和数据库服务建立n个连接
max pool size=4 --最大连接池大小:允许建立的最大连接数,是在需要的时候建立。
举例说明:min pool size = 2;max pool size=4 ;
点击按钮时调用以下代码执行数据库脚本。
try { info.Clear(); for (int i = 0; i < num.Value; i++) { Thread th = new Thread(GetCurrentDbName); th.Start(); } } catch (Exception ex) { listboxAdd(ex.Message); }
这里的GetCurrentDbName方法是创建数据库连接然后执行一段SQL脚本,获取当前数据库的名称然后延时3S,所以每次执行SQL的时间都约为3秒
select db_name(); waitfor delay '00:00:03'; --延迟3秒
这里我们先将并发数设为1,在初次建立连接时会创建2个连接。
可以在数据库中进行查看:
select * from sysprocesses where hostname='xxx' and loginame='test'
2. 那连接池是和什么有关呢?
在同一个进程中,只和连接字符串有关,只要连接字符串一样就会使用同一个连接池。
这里我们将连接字符串改为下图(只修改了最小数据池):
执行指令后,再观察一下数据库的连接信息:
我们发现会多出一个连接信息,可以会怀疑是不是使用的同个连接池。你可以将并发数改为4.
可以看到,这时的连接数变为6,之前的连接字符串占用了两个,修改后的占用了4个。因为连接池的大小限制为4,所以说明确实是使用了两个连接池。
当我们的并发请数大于最大连接池数会怎么样?这里我们修改一下之前的程序代码,记录线程调用方法执行的起止时间
9个线程的执行截止时间,可以看出前四的截止时间基本相同,中间的四个大约比前4个晚3S。最后一个比中间四个晚3S。
说明开始有4个线程的数据库请求获取到连接池资源,其它线程等待。
这4个线程执行完成后,另4个线程获的连接池资源,最后一个线程等待真到再次释放连接池。
那我们再看一下数据库的连接数仍然为4。说明有多个并行请求时,超过连接池的部分将等待。等待多久会超时呢???
结论是如果想使用连接池,必须使用相同的连接字符串,必须一字不差(我并没有全部测试)。
3.如何使用相同的连接池访问不同的数据库?
在实际开发中我们会访问同一个服务器中的多个数据库,但又不想创建过多的连接。如果访问不同的库使用不同的连接字符串,那就会产生多个连接池。
如这样:
pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = master; User ID = test; Password=Sm5lAXQiZ10L
这时有两个办法:
1.在SQL语句中指定数据库名称(不太靠谱)
2.不要重新创建连接,而是使用的相同的连接字符串创建连接后再切换数据库。实现代码如下:
using (SqlCommand cmd = new SqlCommand(sql, _conn)) { using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { DataSet ds = new DataSet(); _conn.Open(); //这时指向的是tempdb _conn.ChangeDatabase("master"); //切换数据库 adapter.Fill(ds); _conn.Close(); return ds.Tables[0]; } }