本文目錄一覽:
- 1、什麼是mysql連接池,它的主要功能是什麼
- 2、高並發的MySQL數據查詢時,會不會選擇數據庫連接池?
- 3、一般連接池是怎麼處理mysql自動回收長時間
- 4、MySQL與Redis數據庫連接池介紹(圖示+源碼+代碼演示)
- 5、MySql數據庫連接池如何配置
- 6、swoole mysql連接池 有什麼用
什麼是mysql連接池,它的主要功能是什麼
數據連接池是把數據庫連接放到中間服務器上,比如tomcat上,那麼相當於每次你操作數據庫的時候就不需要再”連接”到數據庫再進行相關操作,而是直接操作服務器上的”連接池”,你可以根據字面意思進行理解,把數據庫當做一條小溪,那麼”連接池”就是一個”水池”,這個水池裡面的水是由事先架好的通向”小溪”的水管引進來的,所以,你想喝水的時候不必大老遠地跑到小溪邊上,而只要到這個水池就可以.這樣的話就可以提高”效率”.但是數據池一般是用在數據量比較大的項目,這樣可以提高程序的效率,想一想這樣的話是不是就把相關的負荷加在了服務器上,因為這個”池”是在服務器上的,對於小數據量處理的項目不推薦使用,應為過於頻繁的請求會使得服務器負載加重
關係:
你 –“水池”–小溪(快速喝水)
程序–“數據池”–數據庫(快速存取)
就是這樣,也不用把它想神秘了,我是這樣理解的,也就這樣說了,希望對你有幫助
高並發的MySQL數據查詢時,會不會選擇數據庫連接池?
現象
Sysbench對MySQL進行壓測, 並發數過大(5k)時, Sysbench建立連接的步驟會超時.
猜想
猜想: 直覺上這很簡單, Sysbench每建立一個連接, 都要消耗一個線程, 資源消耗過大導致超時.
驗證: 修改Sysbench源碼, 調大超時時間, 仍然會發生超時.
檢查環境
猜想失敗, 回到常規的環境檢查:
MySQL error log 未見異常.
syslog 未見異常.
tcpdump 觀察網絡包未見異常, 連接能完成正常的三次握手; 只觀察到在出問題的連接中, 有一部分的TCP握手的第一個SYN包發生了重傳, 另一部分沒有發生重傳.
自己寫一個簡單的並發發生器, 替換sysbench, 可重現場景. 排除sysbench的影響
猜想2
懷疑 MySQL 在應用層因為某種原因, 沒有發送握手包, 比如卡在某一個流程上:
檢查MySQL堆棧未見異常, 彷彿MySQL在應用層沒有看到新連接進入.
通過strace檢查MySQL, 發現 accept() 調用確實沒有感知到新連接.
懷疑是OS的原因, Google之, 得到參考文檔: A TCP “stuck” connection mystery【】
分析
參考文檔中的現象跟目前的狀況很類似, 簡述如下:
正常的TCP連接流程:
Client 向 Server 發起連接請求, 發送SYN.
Server 預留連接資源, 向 Client 回復SYN-ACK.
Client 向 Server 回復ACK.
Server 收到 ACK, 連接建立.
在業務層上, Client和Server間進行通訊.
當發生類似SYN-flood的現象時, TCP連接的流程會使用SYN-cookie, 變為:
Client 向 Server 發起連接請求, 發送SYN.
Server 不預留連接資源, 向 Client 回復SYN-ACK, 包中附帶有簽名A.
Client 向 Server 回復ACK, 附帶 f(簽名A) (對簽名進行運算的結果).
Server 驗證簽名, 分配連接資源, 連接建立.
在業務層上, Client和Server間進行通訊.
當啟用SYN-cookie時, 第3步的ACK包因為 某種原因 丟失, 那麼:
從Client的視角, 連接已經建立.
從Server的視角, 連接並不存在, 既沒有建立, 也沒有”即將建立” (若不啟用SYN-cookie, Server會知道某個連接”即將建立”)
發生這種情況時:
若業務層的第一個包應是從 Client 發往 Server, 則會進行重發或拋出連接錯誤
若業務層的第一個包應是從 Server 發往 Client的, Server不會發出第一個包. MySQL的故障就屬於這種情況.
TCP握手的第三步ACK包為什麼丟失
參考文檔中, 對於TCP握手的第三步ACK包的丟失原因, 描述為:
Some of these packets get lost because some buffer somewhere overflows.
我們可以通過Systemtap進一步探究原因. 通過一個簡單的腳本:
probe kernel.function(“cookie_v4_check”).return
{
source_port = @cast($skb-head + $skb-transport_header, “struct tcphdr”)-source
printf(“source=%d, return=%d\n”,readable_port(source_port), $return)
}
function readable_port(port) {
return (port ((19)-1)) 8 | (port 8)
}
觀察結果, 可以確認cookie_v4_check (syn cookie機制進行包簽名檢查的函數)會返回 NULL(0). 即驗證是由於syn cookie驗證不通過, 導致TCP握手的第三步ACK包不被接受.
之後就是對其中不同條件進行觀察, 看看是哪個條件不通過. 最終原因是accept隊列滿(sk_acceptq_is_full):
static inline bool sk_acceptq_is_full(const struct sock *sk){ return sk-sk_ack_backlog sk- sk_max_ack_backlog;}
恢復故障與日誌的正關聯
在故障處理的一開始, 我們就檢查了syslog, 結論是未見異常.
當整個故障分析完成, 得知了故障與syn cookie有關, 回頭看syslog, 裡面是有相關的信息, 只是和故障發生的時間不匹配, 沒有正關聯, 因此被忽略.
檢查Linux源碼:
if (!queue-synflood_warned
sysctl_tcp_syncookies != 2
xchg(queue-synflood_warned, 1) == 0)
pr_info(“%s: Possible SYN flooding on port %d. %s.
Check SNMP counters.\n”,
proto, ntohs(tcp_hdr(skb)-dest), msg);
可以看到日誌受到了抑制, 因此日誌與故障的正關聯被破壞.
粗看源碼, 每個listen socket只會發送一次告警日誌, 要獲得日誌與故障的正關聯, 必須每次測試重啟MySQL.
解決方案
這種故障一旦形成, 難以檢測; 系統日誌中只會出現一次, 在下次重啟MySQL之前就不會再出現了; Client如果沒有合適的超時機制, 萬劫不復.
解決方案:
1. 修改MySQL的協議, 讓Client先發握手包. 顯然不現實.
2. 關閉syn_cookie. 有安全的人又要跳出來了.
3. 或者調高syn_cookie的觸發條件 (syn backlog長度). 降低系統對syn flood的敏感度, 使之可以容忍業務的syn波動.
有多個系統參數混合影響syn backlog長度, 參看【】
下圖為精華總結
請點擊輸入圖片描述
一般連接池是怎麼處理mysql自動回收長時間
更快速的配置對比 pt-config-diff在我們日常工作中,大家一定遇到過以下場景:
若干套 MySQL 環境,只有一套:
∘ 行為異常,懷疑觸發 bug
∘ 性能異常,比其他環境都要低
在這種場景下,我們一般的做法是首先控制變量,查看軟硬件配置,以及 MySQL 的參數配置。關於 MySQL 的參數配置對比,如果我們人工對比的話只會關注某些重點參數,而缺少了整體細節上的的對比。在這裡我們推薦給大家 Percona Toolkit 中的一個工具 pt-config-diff
更準確的複製延時 pt-heartbeat在 MySQL 中,複製延遲可以理解為由兩部分組成:1. 主庫已經生成了 BINLOG,但是還沒有發送給從庫 — 我們在這裡稱之為:日誌延遲2. 從庫已經接收到了 BINLOG,但是還沒有應用完成 — 我們在這裡稱之為:應用延遲MySQL 原生的查看複製延遲的手段為:show slave status\G中的Seconds_Behind_Master。這種觀測手法只能觀測出應用延遲。在異步複製或降級的半同步複製下,誤差較大,無法準確的反映出整體複製延時。
1. 在 Master 上循環插入:insert into database.heartbeat (master_now) values(NOW())
2. database.heartbeat 的變更會跟隨主從複製流向從庫
3. 系統當前時間 – 從庫表中的時間 = 從庫實際的複製延時
更簡單的參數配置建議 pt-variable-advisortoolkit 中包含了一個簡單的 MySQL 參數優化器,可以對參數配置做簡單的優化建議。
更準確的複製延時 pt-heartbeat在 MySQL 中,複製延遲可以理解為由兩部分組成:1. 主庫已經生成了 BINLOG,但是還沒有發送給從庫 — 我們在這裡稱之為:日誌延遲2. 從庫已經接收到了 BINLOG,但是還沒有應用完成 — 我們在這裡稱之為:應用延遲MySQL 原生的查看複製延遲的手段為:show slave status\G中的Seconds_Behind_Master。這種觀測手法只能觀測出應用延遲。在異步複製或降級的半同步複製下,誤差較大,無法準確的反映出整體複製延時。
更易用的調試工具 pt-pmp在某些情況下,我們肯定會遇到某些故障無法從日誌,以及狀態命令中找到原因,需要深入到程序邏輯級別。又或者我們需要立即通過非常規手段恢復故障數據庫,但是又想保留足夠多的故障信息。來避免我們事後復現問題的頭疼。pt-pmp 便是在這種場景下幫助我們的工具。它會使用 gdb 來打印 mysqld 的堆棧信息,並把調用鏈相同的線程堆棧合併。堆棧合併的功能對於 MySQL 這種多線程的應用非常有幫助,會節省我們大量的時間。
MySQL與Redis數據庫連接池介紹(圖示+源碼+代碼演示)
數據庫連接池(Connection pooling)是程序啟動時建立足夠的數據庫連接,並將這些連接組成一個連接池,由程序動態地對池中的連接進行申請,使用,釋放。
簡單的說:創建數據庫連接是一個很耗時的操作,也容易對數據庫造成安全隱患。所以,在程序初始化的時候,集中創建多個數據庫連接,並把他們集中管理,供程序使用,可以保證較快的數據庫讀寫速度,還更加安全可靠。
不使用數據庫連接池
如果不使用數據庫連接池,對於每一次SQL操作,都要走一遍下面完整的流程:
1.TCP建立連接的三次握手(客戶端與 MySQL服務器的連接基於TCP協議)
2.MySQL認證的三次我收
3.真正的SQL執行
4.MySQL的關閉
5.TCP的四次握手關閉
可以看出來,為了執行一條SQL,需要進行大量的初始化與關閉操作
使用數據庫連接池
如果使用數據庫連接池,那麼會 事先申請(初始化)好 相關的數據庫連接,然後在之後的SQL操作中會復用這些數據庫連接,操作結束之後數據庫也不會斷開連接,而是將數據庫對象放回到數據庫連接池中
資源重用:由於數據庫連接得到重用,避免了頻繁的創建、釋放連接引起的性能開銷,在減少系統消耗的基礎上,另一方面也增進了系統運行環境的平穩性(減少內存碎片以及數據庫臨時進程/線程的數量)。
更快的系統響應速度:數據庫連接池在初始化過程中,往往已經創建了若干數據庫連接置於池中備用。 此時連接的初始化工作均已完成。對於業務請求處理而言,直接利用現有可用連接,避免了從數據庫連接初始化和釋放過程的開銷,從而縮減了系統整體響應時間。
統一的連接管理,避免數據庫連接泄露:在較為完備的數據庫連接池實現中,可根據預先的連接佔用超時設定,強制收回被佔用連接。從而避免了常規數據庫連接操作中可能出現的資源泄露。
如果說你的服務器CPU是4核i7的,連接池大小應該為((4*2)+1)=9
相關視頻推薦
90分鐘搞懂數據庫連接池技術|linux後台開發
《tcp/ip詳解卷一》: 150行代碼拉開協議棧實現的篇章
學習地址:C/C++Linux服務器開發/後台架構師【零聲教育】-學習視頻教程-騰訊課堂
需要C/C++ Linux服務器架構師學習資料加qun 812855908 獲取(資料包括 C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg 等),免費分享
源碼下載
下載方式:(Github中下載)
db_pool目錄下有兩個目錄,mysql_pool目錄為MySQL連接池代碼,redis_pool為redis連接池代碼
下面介紹mysql_pool
CDBConn解析
概念: 代表一個數據連接對象實例
相關成員:
m_pDBPool:該數據庫連接對象所屬的數據庫連接池
構造函數: 綁定自己所屬於哪個數據庫連接池
Init()函數: 創建數據庫連接句柄
CDBPool解析
概念:代表一個數據庫連接池
相關成員:
Init()函數:常見指定數量的數據庫實例句柄,然後添加到m_free_list中,供後面使用
GetDBConn()函數: 用於從空閑隊列中返回可以使用的數據庫連接句柄
RelDBConn()函數: 程序使用完該數據庫句柄之後,將句柄放回到空閑隊列中
測試之前,將代碼中的數據庫地址、端口、賬號密碼等改為自己的(代碼中有好幾處)
進入MySQL, 創建mysql_pool_test數據庫
進入到mysql_pool目錄下, 創建一個build目錄並進入 :
然後輸入如下的命令進行編譯
之後就會在目錄下生成如下的可執行文件
輸入如下兩條命令進行測試: 可以看到不使用數據庫連接池,整個操作耗時4秒左右;使用連接池之後,整個操作耗時2秒左右,提升了一倍
源碼下載
下面介紹redis_pool
測試
進入到redis_pool目錄下, 創建一個build目錄並進入 :
然後輸入如下的命令進行編譯
之後就會在目錄下生成如下的可執行文件
輸入如下的命令進行測試: 可以看到不使用數據庫連接池,整個操作耗時182ms;使用連接池之後,整個操作耗時21ms,提升了很多
進入redis,可以看到我們新建的key:
MySql數據庫連接池如何配置
連接先建立一些連接,並且這些連接允許共享,因此這樣就節省了每次連接的時間開銷。Mysql數據庫為例,連接池在Tomcat中的配置與使用。
1、創建數據庫Student,表student
2、配置server.xml文件。Tomcat安裝目錄下conf中server.xml文件。
GlobalNamingResources
Resource
name=”jdbc/DBPool”
type=”javax.sql.DataSource”
password=””
driverClassName=”com.mysql.jdbc.Driver”
maxIdle=”2″
maxWait=”5000″
username=”root”
url=”jdbc:mysql://localhost:3306/student”
maxActive=”3″
/
/GlobalNamingResources
name:指定連接池的名稱
type:指定連接池的類,他負責連接池的事務處理
url:指定要連接的數據庫
driverClassName:指定連接數據庫使用的驅動程序
username:數據庫用戶名
password:數據庫密碼
maxWait:指定最大建立連接等待時間,如果超過此時間將接到異常
maxIdle:指定連接池中連接的最大空閑數
maxActive:指定連接池最大連接數
3、配置web.xml文件。
web-app
resource-ref
descriptionmysql數據庫連接池配置/description
res-ref-namejdbc/DBPool/res-ref-name
res-typejavax.sql.DataSource/res-type
res-authContainer/res-auth
res-sharing-scopeShareable/res-sharing-scope
/resource-ref
/web-app
4、配置context.xml文件
與server.xml文件所在的位置相同。
Context
ResourceLink
name=”jdbc/DBPool”
type=”javax.sql.DataSource”
global=”jdbc/DBPool”
/
/Context
5、測試
DataSource pool = null;
Context env = null;
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
env = (Context)new InitialContext().lookup(“java:comp/env”);
//檢索指定的對象,返回此上下文的一個新實例
pool = (DataSource)env.lookup(“jdbc/DBPool”);
//獲得數據庫連接池
if(pool==null){out.printl(“找不到指定的連接池!”);}
con = pool.getConnection();
st = con.createStatement();
rs = st.executeQuery(“select * from student”);
}catch(Exception ex){out.printl(ne.toString());}
swoole mysql連接池 有什麼用
對mysql那一端形成一個遠程過程的調用,通過XDR數據結構進行解析mysql傳來的數據項(RPC也為sun最新提出並後來在linux上默認支持),也就是說像用戶登錄驗證這一塊用Mysql的長連接來實現,提高其效率運行相當穩定!
原創文章,作者:M3Q55,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/129307.html