使用Mybatis時請注意這兩個參數,否則會讓你的數據庫連接爆掉

  回去認真讀了Mybatis源碼,發現自己錯了,特此更正,以免誤導讀者,實在是對不起。其實poolMaximumActiveConnections的存在可以正確地限制數據庫連接池併發訪問數據的連接數,沒有問題,之所以我的數據庫爆掉了,是我沒有正確地維持SqlSessionFactory這個類的一個單例。在使用時一定要保持一個全局唯一的SqlSessionFactory 
     上次發帖是在跳槽後,今天爲止已經在新公司工作了兩個星期了,感受什麼的,我另外寫文章再談,言歸正傳,講正事~~! 
     目前正在開發一個產品的服務器端代碼,持久層我選擇了Mybatis3(也就是原來的ibatis)作爲框架,之所以選擇他理由就是我覺得Hibernate搞起來貌似很複雜,我不太會用,哈哈(上家公司留下的陰影,用Hibernate搞得我想死)。上週完成了大部分代碼的開發工作,想着既然是要發佈的產品,於是找來Jmeter做壓力測試,結果這一測,暴露問題了,mysql返回"too many connections"這個error,這個error的具體解釋參照這個鏈接http://dev.mysql.com/doc//refman/5.5/en/too-many-connections.html。 
     一般持久層與數據庫連接都會通過一個連接池(pooled datasource)管理,方便複用連接,控制併發,比較有名的有DBCP,C3P0,BONECP等等。Mybatis3自己實現了一個連接池,在配置文件中指定datasource的type屬性爲POOLED即可使用。與併發關係較大的兩個Mybatis連接池參數是poolMaximumActiveConnectionspoolMaximumIdleConnections。 
      好了,出了問題,自然得找文檔(官方手冊,中英文皆有),poolMaximumActiveConnections是最大的活動連接數,活動連接,顧名思義,就是正在與數據庫交互的連接,默認是10,poolMaximumIdleConnections是空閒連接數,就是沒有處理請求的連接,默認是5。Mysql的max_connections我設置的是200,既最大連接數。這樣一看,好像找不到問題所在,連接池最大的活動連接也就是10,跟200比還差很遠,Mysql怎麼會返回"too many connections"呢?在查閱文檔無果後,我請教周圍的一位同事,他雖然沒用過Mybatis,但是他說是不是請求數超過poolMaximumActiveConnections後mybatis還會去獲取連接,是不是有這樣的參數控制,然後讓我看看源碼,說開源的東西嘛,搞不清楚就看源碼。 
      我一向對源碼抱有恐懼的心理,感覺那都是大神寫的,我等屌絲怎能看得懂,不過被逼無奈,翻出Mybatis的源碼看了一看,結果豁然開朗。找到org.apache.ibatis.datasource.pooled包下面的PooledDataSource類,這個就是連接池的實現類。可以看到裏面定義了幾個參數,其中就包括poolMaximumActiveConnections和poolMaximumIdleConnections,找到pushConnection方法,這個方法裏會判斷當前空閒連接數和poolMaximumIdleConnections的大小,如果小於他,會new PooledConnection並放進隊列中,這就導致一個問題,當所有的連接被佔滿後,Mybatis爲了保持一定的空閒連接,會不斷獲取新的連接,然後這些新連接被佔用後,就會再去new PooledConnection,結果就是超過了mysql設置的最大連接數,然後數據庫返回該錯誤。不知道這算不算是Mybatis的一個"坑"吧,總之在使用時要小心了,併發量大的時候就會爆掉你的數據庫,解決辦法很簡單,將poolMaximumIdleConnections設置爲0即可,果然改掉後壓力測試不會爆掉數據庫。 
       現在回想起來,官方文檔對poolMaximumIdleConnections的定義是:在任意時間存在的空閒連接數,完全就解釋了這個參數的含義,只不過當時沒有仔細想,那這個參數是不是該改名字叫poolPermanentIdleConnections比較好呢,呵呵。 
問題解決了,很開心,晚上回去再仔細讀下里面的源碼,看看還有沒有別的沒發現的問題。看來源碼也不是想象中的那麼神祕和高深啊。其實爲什麼那個同事一下就能看出問題的大概,一方面是經驗豐富,另一方面可能與他理解數據庫連接池機制有關,歸根到底,基礎的東西還是最重要的。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章