交互式操做:通俗的說,就是你在你的本機上打開mysql的客戶端,就是那個黑窗口,在黑窗口下進行各類sql操做,固然走的確定是tcp協議。html
非交互式操做:就是你在你的項目中進行程序調用。好比一邊是tomcat web服務器,一邊是數據庫服務器,二者怎麼通訊?在java web裏,咱們一般會選擇hibernate或者是jdbc來鏈接。那麼這時候就是非交互式操做。java
在以前,我基本上不關係這兩個屬性,都是用的是mysql服務商推薦的默認值,就是8小時。mysql
可是,從昨天開始,因爲在新網租用了一個空間,而他的mysql的wait_time設置了10s,因此引出來一系列的問題,就順便來研究下。程序員
或者這個標題能夠改成「mysql的8小時自動關閉」問題,這個標題你到百度上搜搜,一搜一大堆,可是都沒有講明白,今天我就給你們來講說這兩個值。web
1、概念sql
1)interactive_time:是指若是空餘Ns(N就是這個屬性的值),那麼就會自動關閉mysql的鏈接。關閉什麼樣的mysql鏈接?在以前,咱們在《什麼是mysql的交互式操做和非交互式操做?》 這篇文章中講到,mysql是有兩種操做方式,那就有兩種鏈接的,一種是交互式,一種是非交互式。而這個屬性控制的是交互式。就是你打開一個mysql客 戶端黑窗口,進入操做以後,又隔了Ns你不操做了,以後你想繼續操做,對不起,mysql會在以前關閉了你的那個鏈接,mysql會幫你自動從新鏈接。數據庫
2)wait_time:是指若是空餘Ns(N就是這個屬性的值),那麼會自動kill掉mysql的一部分鏈接線程。這裏的鏈接就是指的是非交互式鏈接。tomcat
總結下,就是用比較正規的術語講:性能優化
(1)interactive_timeout:服務器
參數含義:服務器關閉交互式鏈接前等待活動的秒數。交互式客戶端定義爲在mysql_real_connect()中使用CLIENT_INTERACTIVE選項的客戶端。
參數默認值:28800秒(8小時)
(2)wait_timeout:
參數含義:服務器關閉非交互鏈接以前等待活動的秒數。
在線程啓動時,根據全局wait_timeout值或全局interactive_timeout值初始化會話wait_timeout值,取決於客戶端類型(由mysql_real_connect()的鏈接選項CLIENT_INTERACTIVE定義)。
參數默認值:28800秒(8小時)
這裏有引出了另一個概念:mysql_real_connect(),這個好理解,就是你無論什麼鏈接,是交互式仍是非交互式,你要操做mysql以前要必須執行完畢的方法,其實你能夠理解成登陸mysql,或者拿到mysql的一個鏈接。
2、如何查看、從新設置這兩個值
查看mysql server超時時間:
msyql> show global variables like '%timeout%';
設置mysql server超時時間(以秒爲單位): 最小設置
msyql> set global wait_timeout=28800;
msyql> set global interactive_timeout=28800;
mysql默認是28800,即8小時。
這是我修改以後的。這是查看方法。
修改這兩個值是分爲兩種修改的。
1) 修改當前會話的這兩個屬性值。所謂的當前會話就是你當前獲取的鏈接池的鏈接。好比你打開黑窗口那個會話。這個修改比較簡單,直接set wait_timeout=10;就好了,你怎麼知道這麼修改僅僅修改的是當前會話?很簡單,你把這個黑窗口關了,你再從新開一個,再從新查,你發現沒改 啊。
2)修改全局的屬性值。通常這個用的多,你到你的數據庫安裝包下找到my.ini,在最下面添加wait_timeout=10就能夠了,而後從新啓動mysql服務,我說的從新啓動服務,不是你關閉這個黑窗口,從新啓動一個黑窗口。服務在個人電腦右鍵服務裏去找。
如今先說到這裏,一會繼續。
1、mysql8小時異常
1)異常概念。
大 家都知道mysql的8小時自動斷開異常吧,百度上一大把。就是因爲這個值形成的,這個值mysql默認的是8小時,因此若是你在8小時內,數據庫以爲沒 有任何人來鏈接我,那好,我就將全部的如今存在的非交互式鏈接所有kill掉。而ssh中,咱們通常用的是數據池。就是在tomcat已啓動的時候,就向 mysql申請到N(這個N是你配置的)個非交互是鏈接,之後想要用數據庫鏈接的時候,沒有必要一個請求就去從新獲取mysql鏈接,只要從數據池裏獲取 就能夠了。可是如今若是你8小時以內,沒有發送請求,那麼mysql會自動將全部的非交互是鏈接kill掉,那這時候,你的數據庫鏈接池裏存在的數據庫連 接實際上是null,是不存在的,你這時候也不判斷,繼續想用這個連接去請求數據,固然會拋出異常,所拋出的異常Communications link failure due to underlying exception。
2)那麼如何解決呢?
原 理很簡單,出現這個異常的緣由不就是由於鏈接池裏存在着已經不存在的鏈接,並且你還不知道,你還得用這個本來就被關閉的鏈接去請求嗎?這就好辦了,你控制 了不了服務器的mysql(若是你是空間的話),那你知道控制本身的數據庫鏈接池了,讓鏈接池增長一個驗證功能,就是凡是在從池裏拿到鏈接以後,在用以前 先驗證下這個連接是否有效,若是有效則能夠直接使用,若是無效則從新申請一個鏈接,這樣就不會出現這個異常了。固然,確定性能會下降。關於性能爲何降 低,咱們稍後會講,如今來看,如何實現讓數據庫鏈接池先驗證是否有效再用的功能:
我用的鏈接池是c3p0,建議使用這個。固然各個鏈接池的性能優缺點你得根據本身的項目具體分析,這裏可不分析我爲何選c3p0了。
1
2
|
<
property
name
=
"testConnectionOnCheckin"
value
=
"true"
/>//歸還給鏈接池時候要檢查
<
property
name
=
"testConnectionOnCheckout"
value
=
"true"
/>//從鏈接池中拿出來要檢查
|
1
2
3
4
5
6
7
|
<!--因性能消耗大請只在須要的時候使用它。若是設爲true那麼在每一個connection提交的
時候都將校驗其有效性。建議使用idleConnectionTestPeriod或automaticTestTable
等方法來提高鏈接測試的性能。Default: false -->
<
property
name
=
"testConnectionOnCheckout"
>false</
property
>
<!--若是設爲true那麼在取得鏈接的同時將校驗鏈接的有效性。Default: false -->
<
property
name
=
"testConnectionOnCheckin"
>true</
property
>
|
因此也就是經過兩個動做去維護這個鏈接池,如圖:
3)解決方案的性能問題
A)檢測有效性的性能優化
由於要去時刻檢查這個連接是否還有效,因此效率好比會下降,那麼如何檢查呢?默認的檢查方式我如今還真不知道,可是上面一段話說了,若是使用 automaticTestTable 方法進行驗證測試鏈接的有效性,會對性能有所提高。那咱們就來看下這個屬性
1
|
<
property
name
=
"automaticTestTable"
value
=
"C3P0TestTable"
/>
|
這 個屬性是什麼意思呢?就是他會自動的幫你創建一張名字叫C3P0TestTable的表,這種表很是的簡單,並且最關鍵的是裏面沒有數據,檢測的時候,可 以經過鏈接訪問這種表是否能訪問的到,若是能訪問的到,說明這個連接是有效的,不然說明這個連接已經被mysql kill掉了。
那這張表是咱們程序員創建的嗎?NO,你不用管,你只要這麼配置上,天然會幫你自動創建一張這個表的。
B)testConnectionOnCheckout 性能的優化。由於這個屬性是指你從鏈接池中拿出來的時候,在每個連接去真正提交,震中拿着這個連接去數據庫訪問的時候,要作下檢查,並非說,我從鏈接 池中拿出來,我就作檢查,我得等到提交的時候才作檢查的,那這樣會設計到一個connection提交的問題,在默認的狀況下,你發送一個db request就會自動立刻去執行,就會立刻commit的,若是你配置在事務當中呢,就是一個action方法對應一個biz方法,這樣你只要作一次檢 查就好了,減小了檢測的次數。
也就是說,對於這種解決方案的性能優化的宗旨就是減小檢測次數、優化檢測方法。
2、mysql的wait_timeout值應該設置多少?
若是你不是IDC,你不是往外出租服務器,那麼你徹底能夠設置爲默認值8小時就能夠了。可是若是IDC往外租用服務器的時候,就得從新設置了,好比新網就是設置爲10s的。
但 是這個設置爲多大,並非新網那樣隨便設置的,由於我發現新網的這個服務器業務壓力並非很大,可是他卻設置了一個10s這麼小的值,這樣反而會更消耗服 務器資源。是,得認可,若是這個值過大的話,極可能會形成大量的無用的閒置的鏈接存在,對數據庫壓力過大,可是新網的那個服務器的業務壓力並不大啊,你設 置成這麼小的數值,很明顯,你是在刻意的增長系統服務器的業務壓力啊,罪人啊罪人。
因此,設置爲多大,得根據你的服務器的壓力大小來配置的,可不是隨便寫一個數就好了的。