Mysql超時(shí)配置項(xiàng)的深入理解
1 JDDB超時(shí)
JDBC 是 Java 應(yīng)用程序中用于訪問數(shù)據(jù)庫的一套標(biāo)準(zhǔn) API
類型4驅(qū)動(dòng)是通過socket來處理字節(jié)流的。如果socket超時(shí)設(shè)置不合適,類型4驅(qū)動(dòng)也可能有同樣的錯(cuò)誤(連接被阻塞)。
1.2 JDBC超時(shí)層次
應(yīng)用程序WAS與數(shù)據(jù)庫間的超時(shí)的層次
更上層的超時(shí)依賴于下層的超時(shí),只有當(dāng)較低層的超時(shí)機(jī)制正常工作,上層的超時(shí)才會(huì)正常。
1.2.1 事務(wù)超時(shí)
事務(wù)超時(shí)是在框架(Spring、EJB容器)或應(yīng)用程序?qū)用嫔喜庞行У某瑫r(shí)。 在 Spring 中,事務(wù)超時(shí)可以 XML文件配置或在 Java 代碼中用 Transactional 注解來配置。
Spring 中數(shù)據(jù)庫連接被保存在線程本地變量(ThreadLocal)中,這被稱作事務(wù)同步(Transaction Synchronization)。當(dāng)數(shù)據(jù)庫連接被保存到 ThreadLocal 時(shí),同時(shí)會(huì)記錄事務(wù)的開始時(shí)間和超時(shí)時(shí)間。所以通過數(shù)據(jù)庫連接的代理創(chuàng)建的 Statement 在執(zhí)行時(shí)就會(huì)校驗(yàn)這個(gè)時(shí)間。
1.2.2 Statement 超時(shí)
Statement 超時(shí)是用來限制 Statement 的執(zhí)行時(shí)間的,它的具體值是通過 JDBC API 來設(shè)置的。JDBC 驅(qū)動(dòng)程序基于這個(gè)值進(jìn)行 Statement 執(zhí)行時(shí)的超時(shí)處理。Statement 超時(shí)是通過 JDBC API 中java.sql.Statement
類的 setQueryTimeout(int timeout)
方法配置的。不過現(xiàn)在更多是通過框架來進(jìn)行設(shè)置。
以 iBatis 為例,可以通過 SqlMapConfig.xml
中的 settings
屬性defaultStatementTimeout
來設(shè)置全局的statement超時(shí)
缺省值。
也可以通過在具體的 sql 映射文件中的 select insert update
標(biāo)簽的 timeout
屬性來覆蓋。
JDBC的statement timeout處理過程
每個(gè)數(shù)據(jù)庫和驅(qū)動(dòng)程序的Statement超時(shí)的處理也是不同的。MySQL (5.0.8) 中的 Statement 超時(shí)處理如下:
調(diào)用 Connection 的 createStatement() 方法創(chuàng)建一個(gè) Statement 對(duì)象
調(diào)用 Statement 的 executeQuery() 方法
Statement 通過內(nèi)部的 Connection 將查詢命令傳輸?shù)?MySqlServer 數(shù)據(jù)庫
Statement 創(chuàng)建一個(gè)新的超時(shí)執(zhí)行線程(timeout-execution)來處理超時(shí)
5.1以上版本改為每個(gè)連接分配一個(gè)線程
向timeout-execution 線程注冊(cè)當(dāng)前的 Statement
發(fā)生超時(shí)
timeout-execution 線程創(chuàng)建一個(gè)相同配置的 Connection
用新創(chuàng)建的 Connection 發(fā)送取消查詢的命令
1.2.3 JDBC的socket timeout
Socket超時(shí)可以通過 JDBC 驅(qū)動(dòng)程序配置。通過設(shè)置 Socket 超時(shí),可以防止出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤時(shí)一直等待的情況并縮短故障時(shí)間。 Socket 超時(shí)的值必須要高于 Statement 的超時(shí)時(shí)間,否則Socket超時(shí)將會(huì)先生效。
Socket 連接時(shí)的超時(shí):通過 Socket 對(duì)象的
connect(SocketAddress endpoint, int timeout)
方法來配置Socket 讀寫時(shí)的超時(shí):通過 Socket 對(duì)象的
setSoTimeout(int timeout)
方法來配置
MySQL驅(qū)動(dòng)的socket timeout配置方式
- 連接超時(shí)配置 :connectTimeout(默認(rèn)值:0,單位:ms)
- Socket超時(shí)配置: socketTimeout(默認(rèn)值:0,單位:ms)
示例: jdbc:mysql://xxx.xx.xxx.xxx:3306/database?connectTimeout=60000&socketTimeout=60000
也可以通過屬性進(jìn)行配置,而無需直接使用 DBCP 的 API 。
1.2.4 操作系統(tǒng)Socket超時(shí)
操作系統(tǒng)同樣能夠?qū)ocket timeout進(jìn)行配置。 通常,應(yīng)用會(huì)在調(diào)用Socket.read()時(shí)由于網(wǎng)絡(luò)問題被阻塞住,而很少在調(diào)用Socket.write()時(shí)進(jìn)入waiting狀態(tài)。如果系統(tǒng)內(nèi)核緩沖區(qū)由于某種網(wǎng)絡(luò)錯(cuò)誤而滿了的話,Socket.write()也會(huì)進(jìn)入waiting狀態(tài)。這種情況下,操作系統(tǒng)會(huì)嘗試重新發(fā)包,當(dāng)達(dá)到重試的時(shí)間限制時(shí),將產(chǎn)生系統(tǒng)錯(cuò)誤。
2 Mysql服務(wù)器超時(shí)配置
mysql> show variables like '%timeout%'; +-----------------------------+----------+ | Variable_name | Value | +-----------------------------+----------+ | connect_timeout | 10 | | delayed_insert_timeout | 300 | | innodb_flush_log_at_timeout | 1 | | innodb_lock_wait_timeout | 50 | | innodb_rollback_on_timeout | OFF | | interactive_timeout | 28800 | | lock_wait_timeout | 31536000 | | net_read_timeout | 30 | | net_write_timeout | 60 | | rpl_stop_slave_timeout | 31536000 | | slave_net_timeout | 3600 | | wait_timeout | 28800 | +-----------------------------+----------+
2.1 connect_timeout
connect_timeout指的是連接過程中握手的超時(shí)時(shí)間,在5.0.52以后默認(rèn)為10秒,之前版本默認(rèn)是5秒。官方文檔是這樣說的:
connect_timeout: The number of seconds that the mysqld server waits for a connect packet before responding with Bad handshake. The default value is 10 seconds as of MySQL 5.0.52 and 5 seconds before that
connect timeout就是tcp連接超時(shí) 其中又分兩種,一種是超過了自己設(shè)置的連接超時(shí)時(shí)間 一種是tcp層面連接sync包報(bào)文達(dá)到了重試次數(shù)報(bào)的超時(shí), 兩種超時(shí)錯(cuò)誤提示信息是不一樣的。
2.2 interactive_timeout & wait_timeout
wait_timeout和interactive_timeout都是指不活躍的連接超時(shí)時(shí)間,連接線程啟動(dòng)的時(shí)候wait_timeout會(huì)根據(jù)是交互模式還是非交互模式被設(shè)置為這兩個(gè)值中的一個(gè)。 如果我們運(yùn)行mysql -uroot -p
命令登陸到mysql,wait_timeout
就會(huì)被設(shè)置為interactive_timeout的值
2.3 net_read_timeout & net_write_timeout
net_read_timeout和net_write_timeout這個(gè)參數(shù)只對(duì)TCP/IP鏈接有效,分別是數(shù)據(jù)庫等待接收客戶端發(fā)送網(wǎng)絡(luò)包和發(fā)送網(wǎng)絡(luò)包給客戶端的超時(shí)時(shí)間
The number of seconds to wait for more data from a connection before aborting the read. When the server is reading from the client, net_read_timeout is the timeout value controlling when to abort. When the server is writing to the client, net_write_timeout is the timeout value controlling when to abort
這兩個(gè)參數(shù)控制由于網(wǎng)絡(luò)原因造成的異常超時(shí)。比如server在從client端讀取大量的數(shù)據(jù),讀著讀著突然發(fā)現(xiàn)讀不到了,也沒有遇到結(jié)束標(biāo)識(shí)符,這種情況下,server在等待net_read_timeout秒還沒讀到后續(xù)數(shù)據(jù),就斷開連接;或者當(dāng)server select出了大量數(shù)據(jù)發(fā)向客戶端,發(fā)著發(fā)著,突然發(fā)現(xiàn)發(fā)不動(dòng)了,客戶端不接收了,而數(shù)據(jù)還沒有發(fā)送完,這時(shí)server在等待net_write_timeout秒后就斷開連接。
是mysql應(yīng)用層的協(xié)議,而tcp的寫超時(shí)只有在丟包次數(shù)過多才會(huì)。
3 Mysql客戶端
示例
jdbc:mysql://192.168.1.8:3306/mytest?serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&connectTimeout=60000&socketTimeout=60000
connectTimeout
建立鏈接需要的時(shí)間。該參數(shù)只在建立鏈接階段生效。默認(rèn)是0,不超時(shí)。建議配置connectTimeout=60000,單位毫秒。
socketTimeout
發(fā)送請(qǐng)求給數(shù)據(jù)庫(建立鏈接后),數(shù)據(jù)庫處理的最大時(shí)間;默認(rèn)是0,不超時(shí)。建議配置socketTimeout=60000,單位毫秒。
超過這個(gè)客戶端報(bào)超時(shí)超時(shí)異常Caused by: java.net.SocketTimeoutException: Read timed out
。
autoReconnect
是否自動(dòng)重連。默認(rèn)false。mysql服務(wù)端參數(shù)wait_timeout,其默認(rèn)值為 28800秒(8小時(shí)),其意義為如果一個(gè)連接閑置超過這個(gè)選項(xiàng)所設(shè)置的秒數(shù),MySQL會(huì)主動(dòng)斷開這個(gè)連接。如果無法保證應(yīng)用程序在設(shè)定的秒數(shù)內(nèi)至少有一次操作,添加autoReconnect=true這個(gè)參數(shù),即能解決這個(gè)問題。
maxReconnects
autoReconnect設(shè)置為true時(shí),重試連接的次數(shù),默認(rèn)3。
initialTimeout
autoReconnect設(shè)置為true時(shí),兩次重連之間的時(shí)間間隔,默認(rèn)2,單位:秒
4 Mysql連接池配置
4.1 Druid連接池配置
DruidDataSource參考配置 github.com/alibaba/dru…
4.1.1 連接池的初始值、最大值、最小值
initialSize: 5 minIdle: 6 maxActive: 10
項(xiàng)目啟動(dòng)時(shí),會(huì)自動(dòng)初始化initialSize
個(gè)連接出來(沒有流量訪問數(shù)據(jù)庫也會(huì)創(chuàng)建),這幾個(gè)鏈接會(huì)一直存在??梢酝ㄟ^數(shù)據(jù)庫命令SHOW PROCESSLIST
查看初始化的鏈接。
4.1.2 獲取連接的等待時(shí)間
maxWait: 6000
獲取連接池中的連接時(shí)的最大等待時(shí)間,單位是毫秒。
如果這個(gè)時(shí)間內(nèi)未獲得可用鏈接則報(bào)錯(cuò):nested exception is com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 6000, active 10, maxActive 10, creating 0
。這個(gè)報(bào)錯(cuò)表明獲取鏈接超時(shí)了,而且數(shù)據(jù)庫的10個(gè)鏈接都被占用,也不能創(chuàng)建新的鏈接了。
4.1.3 回收連接池中的鏈接
timeBetweenEvictionRunsMillis: 2000 minEvictableIdleTimeMillis: 10000
每隔timeBetweenEvictionRunsMillis: 2000ms
對(duì)連接池的連接做一次檢查, 如果有連接空閑時(shí)間超過minEvictableIdleTimeMillis: 10000ms
就回收該鏈接。
4.1.4 校驗(yàn)鏈接池中的鏈接是否有效
validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false validationQueryTimeout:10
校驗(yàn)的方式:使用待校驗(yàn)的連接在在數(shù)據(jù)庫上執(zhí)行一下校驗(yàn)的sql,這里使用SELECT 1
,一定要保證改sql是該數(shù)據(jù)能執(zhí)行的,不同的數(shù)據(jù)庫的校驗(yàn)sql可能不一樣。
校驗(yàn)的時(shí)機(jī): 通常是在連接空閑時(shí)校驗(yàn)(testWhileIdle: true),
也可以在獲取連接時(shí)校驗(yàn)(testOnBorrow: true,這個(gè)配置會(huì)降低性能),
也可以在歸還連接到連接池時(shí)校驗(yàn)(testOnReturn: true,這個(gè)配置會(huì)降低性能)。
validationQueryTimeout是檢測(cè)連接是否有效的超時(shí)時(shí)間,單位:秒。
如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會(huì)起作用。
4.1 HikariCP配置
4.2.1 連接池的最大值、最小值
maximumPoolSize: 池中最大連接數(shù),包括閑置和使用中的連接。默認(rèn)為 10
。如果 maxPoolSize 小于1,則會(huì)被重置。當(dāng) minIdle <=0 被重置為DEFAULT_POOL_SIZE 則為 10;如果 minIdle > 0 則重置為 minIdle 的值。
minimumIdle: 控制連接池空閑連接的最小數(shù)量,當(dāng)連接池空閑連接少于 minimumIdle,而且總共連接數(shù)不大于 maximumPoolSize 時(shí),HikariCP 會(huì)盡力補(bǔ)充新的連接。為了性能考慮,不建議設(shè)置此值,而是讓 HikariCP 把連接池當(dāng)做固定大小的處理,默認(rèn) minimumIdle 與 maximumPoolSize 一
樣。當(dāng) minIdle < 0 或者 minIdle > maxPoolSize,則被重置為 maxPoolSize,該值默認(rèn)為 10。
4.2.2 獲取連接的等待時(shí)間
connectionTimeout: 等待來自池的連接的最大毫秒數(shù),默認(rèn)為 30000 ms = 30 s
,允許最小時(shí)間是 250 毫秒,如果小于 250 毫秒,則被重置回 30 秒。
4.2.3 超時(shí)時(shí)間
idleTimeout: 連接允許在池中閑置的最長時(shí)間。
如果 idleTimeout + 1 秒 > maxLifetime 且 maxLifetime > 0,則會(huì)被重置為 0(代表永遠(yuǎn)不會(huì)退出);只有當(dāng) minimumIdle 小于 maximumPoolSize 時(shí),這個(gè)參數(shù)才生效
,當(dāng)空閑連接數(shù)超過 minimumIdle,而且空閑時(shí)間超過 idleTimeout,則會(huì)被移除。
這是hikaricp用來判斷是否應(yīng)該從連接池移除空閑連接的一個(gè)重要的配置。負(fù)責(zé)剔除的也還是HouseKeeper這個(gè)定時(shí)任務(wù),值為0時(shí),HouseKeeper不會(huì)移除空閑連接,直到到達(dá)maxLifetime后,才會(huì)移除,默認(rèn)值也就是0。
maxLifetime:
池中連接最長生命周期。默認(rèn)為 1800000, 30 分鐘
。 Mysql 為了防止空閑連接浪費(fèi),占用資源,在超過wait_timeout 時(shí)間后,會(huì)主動(dòng)關(guān)閉該連接,清理資源。 但是hikaricp如何知道池子里維護(hù)的一把連接,有沒有被mysql回收呢?所以就有了maxLifetime
這個(gè)配置,官方也強(qiáng)烈建議必須按需設(shè)置此值!自然這個(gè)值也應(yīng)該小于mysql的wait_timeout
。 那hikaricp在空閑連接
超過maxLifetime
,就會(huì)從連接池中剔除,防止業(yè)務(wù)進(jìn)程取到了已關(guān)閉的連接,導(dǎo)致業(yè)務(wù)受損。
keepaliveTime & connectionTestQuery
keepaliveTime類比tcp的keepAlive機(jī)制。為了防止獲取到被mysql關(guān)閉的無效連接,導(dǎo)致業(yè)務(wù)出錯(cuò)的一種兜底掃描方案。
具體過程就是每隔keepaliveTime時(shí)間間隔,去和數(shù)據(jù)庫發(fā)送心跳,來探測(cè)連接是否有效。如果發(fā)現(xiàn)是無效的,就會(huì)及時(shí)從連接池中剔除,來保證業(yè)務(wù)進(jìn)程獲取到的都是有效連接。
如果配置了connectionTestQuery
,如 select 1
, 心跳檢查過程就會(huì)調(diào)用connectionTestQuery。
所以如果你配置了connectionTestQuery
但是沒有配置keepaliveTime
,是沒有用的,因?yàn)槟J(rèn)是關(guān)閉的。
而connectionTestQuery
配置項(xiàng),官方建議如果驅(qū)動(dòng)支持JDBC4,不要設(shè)置此屬性!
因?yàn)橄啾扔谕ㄟ^select查詢方式探活,mysql 自帶的ping命令 性能更高(直接在sql server返回結(jié)果,就不會(huì)做語法解析,執(zhí)行優(yōu)化,再通過存儲(chǔ)引擎操作)。 而基本上java mysql驅(qū)動(dòng)包5以上的版本都支持JDBC4。
總結(jié)
到此這篇關(guān)于Mysql超時(shí)配置項(xiàng)的文章就介紹到這了,更多相關(guān)Mysql超時(shí)配置項(xiàng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
聽說mysql中的join很慢?是你用的姿勢(shì)不對(duì)吧
這篇文章主要介紹了聽說mysql中的join很慢?是你用的姿勢(shì)不對(duì)吧,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09mysql使用字符串字段判斷是否包含某個(gè)字符串的方法
在MySQL中,判斷字符串字段是否包含特定子字符串,可使用LIKE操作符、INSTR()函數(shù)、LOCATE()函數(shù)、POSITION()函數(shù)、FIND_IN_SET()函數(shù)以及正則表達(dá)式REGEXP或RLIKE,每種方法適用于不同的場景和需求,LIKE和INSTR()通常用于簡單包含判斷2024-09-09使用innodb_force_recovery解決MySQL崩潰無法重啟問題
這篇文章主要介紹了使用innodb_force_recovery解決MySQL崩潰無法重啟問題,這只一個(gè)成功案例,并不是萬能的解決方法,需要酌情考慮,需要的朋友可以參考下2015-05-05Mysql存儲(chǔ)過程和函數(shù)區(qū)別介紹
這篇文章主要介紹了Mysql存儲(chǔ)過程和函數(shù)的區(qū)別,需要的朋友可以參考下2014-03-03MySQL?8.0?對(duì)?limit?的優(yōu)化技巧
從不同版本的 MySQL 發(fā)展軌跡來看 MySQL 的優(yōu)化器越來越智能 (比如大家期待已久的直方圖特性) ,能更多的減少人為干預(yù),提升執(zhí)行計(jì)劃的準(zhǔn)確性,這篇文章主要介紹了MySQL?8.0?對(duì)?limit?的優(yōu)化,需要的朋友可以參考下2022-10-10mysql存儲(chǔ)過程之錯(cuò)誤處理實(shí)例詳解
這篇文章主要介紹了mysql存儲(chǔ)過程之錯(cuò)誤處理,結(jié)合實(shí)例形式詳細(xì)分析了mysql存儲(chǔ)過程錯(cuò)誤處理相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-12-12