mysql經(jīng)典的8小時問題-wait_timeout

前段時間 現(xiàn)網(wǎng)突然頻繁報出 連接不上數(shù)據(jù)庫,偶滴的妖孽,其他地方都是用mysql,也沒遇到這個問題呀。

java.io.EOFExceptionat 
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)

場景出現(xiàn)的理論依據(jù)
MySQL 的默認設(shè)置下,當一個連接的空閑時間超過8小時后,MySQL 就會斷開該連接,而 c3p0/dbcp 連接池則以為該被斷開的連接依然有效。在這種情況下,如果客戶端代碼向c3p0/dbcp 連接池請求連接的話,連接池就會把已經(jīng)失效的連接返回給客戶端,客戶端在使用該失效連接的時候即拋出異常。

如果你只是個程序員,你會想著,在去對數(shù)據(jù)庫做操作前,我不是先對數(shù)據(jù)庫連接做個校驗或判斷什么的,連接是working的,我才干活,那么你得到的解決方案-或許就是這樣的

#c3p0配置
<!--最大空閑時間,60秒內(nèi)未使用則連接被丟棄。若為0則永不丟棄。默認值: 0 -->   
<property name="maxIdleTime">60</property>  
<!-- 當連接池連接耗盡時,客戶端調(diào)用getConnection()后等待獲取新連接的時間,
超時后將拋出SQLException,如設(shè)為0則無限期等待。單位毫秒。默認: 0 -->   
<property name="checkoutTimeout" value="3000"/>  
<!--c3p0將建一張名為Test的空表,并使用其自帶的查詢語句進行測試。
如果定義了這個參數(shù)那么屬性preferredTestQuery將被忽略。
你不能在這張Test表上進行任何操作,它將只供c3p0測試使用。默認值: null -->   
 <property name="automaticTestTable">Test</property>  
<!--因性能消耗大請只在需要的時候使用它。如果設(shè)為true那么在每個connection提交的   
  時候都將校驗其有效性。建議使用idleConnectionTestPeriod或automaticTestTable   
  等方法來提升連接測試的性能。Default: false -->   
<property name="testConnectionOnCheckout">false</property>   
<!--如果設(shè)為true那么在取得連接的同時將校驗連接的有效性。Default: false -->   
<property name="testConnectionOnCheckin">true</property> 
<!--每60秒檢查所有連接池中的空閑連接。Default: 0 -->   
<property name="idleConnectionTestPeriod">60</property>  

如果你只是個DBA,你會想著,為什么數(shù)據(jù)庫連接自己斷了,是不是哪里有配置,我得去看看,那么你得到的解決方案-可能就是這樣的

#my.cnf
wait_timeout=31536000  
interactive_timeout=31536000  

加大wait_timeout的時間。

But 現(xiàn)實環(huán)境中需要你考慮的是:

  1. 你設(shè)置多久檢查一次連接有效的時間 依據(jù)是什么?
  2. 默認加大/減小wait_timeout除了解決當前問題,會不會帶來其他影響?

個人當前覺得此題 第一需考慮的是:
你業(yè)務(wù)當前高峰期mysql_connection是多少?保留多久connection在高峰期都不會撐爆你數(shù)據(jù)庫連接池?
如果你知道這個池-那么是改mysql ?還是改c3p0?還是雙管齊下都是有據(jù)可循且不會帶來后遺癥的-最佳解決方案

如我當前有環(huán)境,一個現(xiàn)網(wǎng)的后臺管理系統(tǒng),使用人數(shù)在50以內(nèi),那么我wait_timeout 就是默認8小時,c3p0不用做連接有效性檢查等,都是萬事ok的。

而我還有一個EPG前臺管理系統(tǒng),用戶量在300萬以內(nèi),如果我wait_timeout為8小時,那我一到高峰期肯定就是死翹翹的,會有太多的TCP連接沒關(guān)閉,
數(shù)據(jù)庫連接數(shù)肯定是不夠的。
因EPG的一個訪問-一次對數(shù)據(jù)庫操作量不大,查詢完數(shù)據(jù)就完成ok啦,wait_timeout 設(shè)置在120s內(nèi)應(yīng)該是夠用啦,那么相對應(yīng)的c3p0中 設(shè)置小于wait_timeout 的時間有效性檢查 -就能確保獲取到連接是有效的。

請根據(jù)業(yè)務(wù)場景,來配置參數(shù),不要解決了A問題,帶來了B問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容