程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> 淺析數據庫連接池(一)

淺析數據庫連接池(一)

編輯:DB2教程

淺析數據庫連接池(一)


由於最近項目要用到數據庫連接池,所以今天簡單的聊聊~,

這個話題的引起是因為我在寫mysql數據庫部分時產生了一個疑問,一般後台處理數據部分,服務端是創建一個connection連接到數據庫,然後所有的請求通過這一個connection來訪問數據庫,還是每個連接創建一個connction?這個連接需要維持多久?…接下來一起看看

首先目錄1,2是為了引出下面的連接池,因為一般我們僅僅是使用數據庫,而忽略了一些內在的東西,這就可能會出現一些效率方面的問題。

4,5連接池的使用和最優連接池配置選擇我在下一篇博客介紹。


總目錄:
-1.數據庫連接過程是怎樣的?
-2.連接所占用的資源有哪些?
-3.連接池簡介
-4.連接池的使用
-5.最優連接池配置選擇


1.數據庫的連接過程是怎樣的?

數據庫本身也是有一個server端程序在跑的,可以這麼說它也是一個後台服務端的程序,我使用的是mysql,在/etc/init.d下面有個mysql.server,開機即啟動mysql服務器。
我們一般使用mysql -uroot -p只不過是使用了管理員的身份來創建一個connection,從而登錄mysql。
下面仔細說說mysql連接過程


mysql連接分為兩種,一種為unix domain socket,另外一種為基於tcp/ip協議,一般我們如果遠程訪問數據庫肯定是基於tcp/ip的,但是如果我們在本機登錄就會分為使用socket還是tcp/ip。
socket:mysql -h localhost -uroot -p或者mysql -uroot -p
tcp/ip :mysql -h 127.0.0.1 -uroot -p

為了證明,我用tcpdump抓個包看看^_^
socket:
這裡寫圖片描述
可以看到unix domain socket並沒有被抓到,因為它是不經過網卡的,本地的。
tcp/ip:
這裡寫圖片描述

tcp/ip就抓到數據了,由此我們可以看出mysql的連接過程,內部實際上是經過tcp/ip協議的,當然mysql封裝了tcp/ip有自己的一套協議。<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPs/Cw+bO0sO/1rTQ0NK7zPVzcWzT777ktry74dPQttTTprXEyv2+3bD8o6zEx8O0utzD98/UwctteXNxbLXEway907e9yr26zc2o0MW3vcq9o6zU2s3Ls/ZteXNxbMqx16W1vcHLNMz1yv2+3aOsNLTOu9PK1t/CoaM8L3A+DQo8cD6+3bnZzfjLtXVuaXggZG9tYWluIHNvY2tldMGsvdO/7NPadGNwL2lwway90zwvcD4NCjxwPkEgTXlTUUwgY2xpZW50IG9uIFVuaXggY2FuIGNvbm5lY3QgdG8gdGhlIG15c3FsZCBzZXJ2ZXIgaW4gdHdvIGRpZmZlcmVudCB3YXlzOiBCeSB1c2luZyBhIFVuaXggc29ja2V0IGZpbGUgdG8gY29ubmVjdCB0aHJvdWdoIGEgZmlsZSBpbiB0aGUgZmlsZSBzeXN0ZW0gKGRlZmF1bHQgL3RtcC9teXNxbC5zb2NrKSwgb3IgYnkgdXNpbmcgVENQL0lQLCB3aGljaCBjb25uZWN0cyB0aHJvdWdoIGEgcG9ydCBudW1iZXIuIEEgVW5peCBzb2NrZXQgZmlsZSBjb25uZWN0aW9uIGlzIGZhc3RlciB0aGFuIFRDUC9JUCwgYnV0IGNhbiBiZSB1c2VkIG9ubHkgd2hlbiBjb25uZWN0aW5nIHRvIGEgc2VydmVyIG9uIHRoZSBzYW1lIGNvbXB1dGVyLiBBIFVuaXggc29ja2V0IGZpbGUgaXMgdXNlZCBpZiB5b3UgZG9uJnJzcXVvO3Qgc3BlY2lmeSBhIGhvc3QgbmFtZSBvciBpZiB5b3Ugc3BlY2lmeSB0aGUgc3BlY2lhbCBob3N0IG5hbWUgbG9jIC1hbGhvc3QuYDxiciAvPg0Ky/nS1M2s0rvMqLXnxNTJz87Sw8e+zcq508N1bml4IGRvbWFpbiBzb2NrZXSwyaGrPC9wPg0KPHA+xuS0zqOsbXlzcWzKx7vhtLS9qNK7uPbP37PMwLS0psDttb3AtLXEway907XEo6zO0sPHv8nS1NTabXlzcWzW0HNob3cgc3RhdHVzO8i7uvPU2sGsvdNteXNxbKOs1Nm0znNob3cgc3RhdHVzvs2/ydLUv7S1vVRocmVhZF9jb25uZWN0ZWS1xMr9wb+74dT2vNMxo6zLtcP3tLS9qMHL0ru49s/fs8zAtLSmwO3V4rj2way906GjPGJyIC8+DQo8aW1nIGFsdD0="這裡寫圖片描述" src="http://www.bkjia.com/uploads/allimg/150613/0412405540-2.png" title="\" />

看上圖,我們可以看到Threads_connected連接數是1,因為此時只有我一個在連接mysql,Threads_created為3,說明曾經有3個connection連接過數據庫,Threads_cached這個是mysql為了提高性能而在內部提供了一個線程的連接池,將空閒的連接不是立即銷毀而是放到線程連接池中,如果新加進來連接不是立刻創建線程而是先從線程連接池中找到空閒的連接線程,然後分配,如果沒有才創建新的線程。可見mysql內部已經為我們做優化了。

Threads_catched值不是無限大的,一般為32左右。
順便說一句,mysql是可以調整單線程和多線程模式的,單線程只允許一個線程連接mysql,其他連接將會被拒絕。
" thread_handling | one-thread-per-connection |


總結並補充上面,那麼數據庫連接的大致為:
1.應用數據層向DataSource請求數據庫連接
2.DataSource使用數據庫Driver打開數據庫連接
3.創建數據庫連接,內部可能創建線程,打開TCP socket
4.應用讀/寫數據庫
5.如果該連接不再需要就關閉連接
6.關閉socket

連接過程就簡單的說到這。


2.連接所占用的資源有哪些?

mysql連接所占資源有哪些?
從上面可以看出來我們一般寫的網絡程序都是基於tcp/ip連接訪問數據庫的,先說下mysql是有最大連接數的。

輸入/usr/bin/mysqladmin -uroot -p variables | grep max_connections
這裡寫圖片描述

我的mysql最大連接數是151,我們可以更改配置文件來改變最大連接數限制,但是否真的好,有待討論,因為系統默認設定肯定會根據系統所能承受的連接或者是給予的資源等等來限定。所以我們就假設不改變參數的情況下所能提供的連接是151。

首先mysql每個連接是會創建一個線程的,可以登錄mysql輸入show status查看Threads_connected和Threads_created的大小,那麼我們每連接一次mysql就會創建一個線程,每次斷開又會銷毀一個線程。

我們都知道創建線程和銷毀線程的資源消耗是非常大的,不然也不會有線程池這個東西了,那麼!從某個角度來看,連接池避免了頻繁的創建連接和銷毀連接(前面我們知道mysql已經做了Threads_catched優化,但是還不夠),其實內部也避免了頻繁的創建線程和銷毀線程!是不是很類似線程池?,就像我的一個學長說的,××池名字聽起來很高大上,其實就那麼回事,原理是相通的,原理很重要。
那麼線程創建和銷毀,以及消耗的資源我們應該很熟悉了。
首先每個線程會分配棧空間,可以通過ulimis -s來查看,我的ubuntu 14.04默認是8M,那麼100個連接就是800M,很吃內存的。其次mysql數據庫會為每個連接分配連接緩沖區和結果緩沖區,也是要消耗時間的。

接著每次每個連接都會進行tcp3次握手和斷開時的4次揮手,分配一些緩存之類的空間,記得曾經看過一點點關於協議棧的東西,裡面的數據結構,等待隊列之類感覺也蠻復雜的,且雖然tcp連接耗費的資源不多,分配的時間也短,但如果我們能夠節省豈不是更好~(關於tcp連接和斷開資源消耗我並沒有深究,抽空再補充吧~,感興趣大家可以查下資料)。


3.連接池簡介

呼~終於到了主題連接池了,其實前面說了這麼多都是為了突出連接池的好……
數據庫連接池技術的思想非常簡單,將數據庫連接作為對象存儲在一個Vector對象中,一旦數據庫連接建立後,不同的數據庫訪問請求就可以共享這些連接,這樣,通過復用這些已經建立的數據庫連接,可以克服上述缺點,極大地節省系統資源和時間。
也就是我們提前創建好這些連接,然後需要用去取連接即可。和線程池的思想是一致的。

這裡寫圖片描述
(圖片來源網絡)

連接池的操作:
(1)建立數據庫連接池對象(服務器啟動)。
(2)按照事先指定的參數創建初始數量的數據庫連接(即:空閒連接數)。
(3)對於一個數據庫訪問請求,直接從連接池中得到一個連接。如果數據庫連接池對象中沒有空閒的連接,且連接數沒有達到最大(即:最大活躍連接數),創建一個新的數據庫連接。
(4)存取數據庫。
(5)關閉數據庫,釋放所有數據庫連接(此時的關閉數據庫連接,並非真正關閉,而是將其放入空閒隊列中。如實際空閒連接數大於初始空閒連接數則釋放連接)。
(6)釋放數據庫連接池對象(服務器停止、維護期間,釋放數據庫連接池對象,並釋放所有連接)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved