Mysql超時(shí)配置項(xiàng)的深入理解
1 JDDB超時(shí)
JDBC 是 Java 應(yīng)用程序中用于訪問(wèn)數(shù)據(jù)庫(kù)的一套標(biāo)準(zhǔn) API

類型4驅(qū)動(dòng)是通過(guò)socket來(lái)處理字節(jié)流的。如果socket超時(shí)設(shè)置不合適,類型4驅(qū)動(dòng)也可能有同樣的錯(cuò)誤(連接被阻塞)。
1.2 JDBC超時(shí)層次
應(yīng)用程序WAS與數(shù)據(jù)庫(kù)間的超時(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 注解來(lái)配置。

Spring 中數(shù)據(jù)庫(kù)連接被保存在線程本地變量(ThreadLocal)中,這被稱作事務(wù)同步(Transaction Synchronization)。當(dāng)數(shù)據(jù)庫(kù)連接被保存到 ThreadLocal 時(shí),同時(shí)會(huì)記錄事務(wù)的開(kāi)始時(shí)間和超時(shí)時(shí)間。所以通過(guò)數(shù)據(jù)庫(kù)連接的代理創(chuàng)建的 Statement 在執(zhí)行時(shí)就會(huì)校驗(yàn)這個(gè)時(shí)間。
1.2.2 Statement 超時(shí)
Statement 超時(shí)是用來(lái)限制 Statement 的執(zhí)行時(shí)間的,它的具體值是通過(guò) JDBC API 來(lái)設(shè)置的。JDBC 驅(qū)動(dòng)程序基于這個(gè)值進(jìn)行 Statement 執(zhí)行時(shí)的超時(shí)處理。Statement 超時(shí)是通過(guò) JDBC API 中java.sql.Statement 類的 setQueryTimeout(int timeout) 方法配置的。不過(guò)現(xiàn)在更多是通過(guò)框架來(lái)進(jìn)行設(shè)置。
以 iBatis 為例,可以通過(guò) SqlMapConfig.xml 中的 settings 屬性defaultStatementTimeout 來(lái)設(shè)置全局的statement超時(shí)缺省值。

也可以通過(guò)在具體的 sql 映射文件中的 select insert update 標(biāo)簽的 timeout 屬性來(lái)覆蓋。

JDBC的statement timeout處理過(guò)程
每個(gè)數(shù)據(jù)庫(kù)和驅(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 通過(guò)內(nèi)部的 Connection 將查詢命令傳輸?shù)?MySqlServer 數(shù)據(jù)庫(kù)
Statement 創(chuàng)建一個(gè)新的超時(shí)執(zhí)行線程(timeout-execution)來(lái)處理超時(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í)可以通過(guò) JDBC 驅(qū)動(dòng)程序配置。通過(guò)設(shè)置 Socket 超時(shí),可以防止出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤時(shí)一直等待的情況并縮短故障時(shí)間。 Socket 超時(shí)的值必須要高于 Statement 的超時(shí)時(shí)間,否則Socket超時(shí)將會(huì)先生效。
Socket 連接時(shí)的超時(shí):通過(guò) Socket 對(duì)象的
connect(SocketAddress endpoint, int timeout)方法來(lái)配置Socket 讀寫時(shí)的超時(shí):通過(guò) Socket 對(duì)象的
setSoTimeout(int timeout)方法來(lái)配置
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
也可以通過(guò)屬性進(jìn)行配置,而無(wú)需直接使用 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ò)問(wèn)題被阻塞住,而很少在調(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指的是連接過(guò)程中握手的超時(shí)時(shí)間,在5.0.52以后默認(rèn)為10秒,之前版本默認(rèn)是5秒。官方文檔是這樣說(shuō)的:
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í) 其中又分兩種,一種是超過(guò)了自己設(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ù)庫(kù)等待接收客戶端發(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)讀不到了,也沒(méi)有遇到結(jié)束標(biāo)識(shí)符,這種情況下,server在等待net_read_timeout秒還沒(méi)讀到后續(xù)數(shù)據(jù),就斷開(kāi)連接;或者當(dāng)server select出了大量數(shù)據(jù)發(fā)向客戶端,發(fā)著發(fā)著,突然發(fā)現(xiàn)發(fā)不動(dòng)了,客戶端不接收了,而數(shù)據(jù)還沒(méi)有發(fā)送完,這時(shí)server在等待net_write_timeout秒后就斷開(kāi)連接。
是mysql應(yīng)用層的協(xié)議,而tcp的寫超時(shí)只有在丟包次數(shù)過(guò)多才會(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ù)庫(kù)(建立鏈接后),數(shù)據(jù)庫(kù)處理的最大時(shí)間;默認(rèn)是0,不超時(shí)。建議配置socketTimeout=60000,單位毫秒。
超過(guò)這個(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è)連接閑置超過(guò)這個(gè)選項(xiàng)所設(shè)置的秒數(shù),MySQL會(huì)主動(dòng)斷開(kāi)這個(gè)連接。如果無(wú)法保證應(yīng)用程序在設(shè)定的秒數(shù)內(nèi)至少有一次操作,添加autoReconnect=true這個(gè)參數(shù),即能解決這個(gè)問(wèn)題。
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è)連接出來(lái)(沒(méi)有流量訪問(wèn)數(shù)據(jù)庫(kù)也會(huì)創(chuàng)建),這幾個(gè)鏈接會(huì)一直存在。可以通過(guò)數(shù)據(jù)庫(kù)命令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ù)庫(kù)的10個(gè)鏈接都被占用,也不能創(chuàng)建新的鏈接了。
4.1.3 回收連接池中的鏈接
timeBetweenEvictionRunsMillis: 2000 minEvictableIdleTimeMillis: 10000
每隔timeBetweenEvictionRunsMillis: 2000ms對(duì)連接池的連接做一次檢查, 如果有連接空閑時(shí)間超過(guò)minEvictableIdleTimeMillis: 10000ms就回收該鏈接。
4.1.4 校驗(yàn)鏈接池中的鏈接是否有效
validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false validationQueryTimeout:10
校驗(yàn)的方式:使用待校驗(yàn)的連接在在數(shù)據(jù)庫(kù)上執(zhí)行一下校驗(yàn)的sql,這里使用SELECT 1,一定要保證改sql是該數(shù)據(jù)能執(zhí)行的,不同的數(shù)據(jù)庫(kù)的校驗(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: 等待來(lái)自池的連接的最大毫秒數(shù),默認(rèn)為 30000 ms = 30 s,允許最小時(shí)間是 250 毫秒,如果小于 250 毫秒,則被重置回 30 秒。
4.2.3 超時(shí)時(shí)間
idleTimeout: 連接允許在池中閑置的最長(zhǎng)時(shí)間。
如果 idleTimeout + 1 秒 > maxLifetime 且 maxLifetime > 0,則會(huì)被重置為 0(代表永遠(yuǎn)不會(huì)退出);只有當(dāng) minimumIdle 小于 maximumPoolSize 時(shí),這個(gè)參數(shù)才生效,當(dāng)空閑連接數(shù)超過(guò) minimumIdle,而且空閑時(shí)間超過(guò) idleTimeout,則會(huì)被移除。
這是hikaricp用來(lái)判斷是否應(yīng)該從連接池移除空閑連接的一個(gè)重要的配置。負(fù)責(zé)剔除的也還是HouseKeeper這個(gè)定時(shí)任務(wù),值為0時(shí),HouseKeeper不會(huì)移除空閑連接,直到到達(dá)maxLifetime后,才會(huì)移除,默認(rèn)值也就是0。
maxLifetime:
池中連接最長(zhǎng)生命周期。默認(rèn)為 1800000, 30 分鐘。 Mysql 為了防止空閑連接浪費(fèi),占用資源,在超過(guò)wait_timeout 時(shí)間后,會(huì)主動(dòng)關(guān)閉該連接,清理資源。 但是hikaricp如何知道池子里維護(hù)的一把連接,有沒(méi)有被mysql回收呢?所以就有了maxLifetime這個(gè)配置,官方也強(qiáng)烈建議必須按需設(shè)置此值!自然這個(gè)值也應(yīng)該小于mysql的wait_timeout。 那hikaricp在空閑連接超過(guò)maxLifetime,就會(huì)從連接池中剔除,防止業(yè)務(wù)進(jìn)程取到了已關(guān)閉的連接,導(dǎo)致業(yè)務(wù)受損。
keepaliveTime & connectionTestQuery
keepaliveTime類比tcp的keepAlive機(jī)制。為了防止獲取到被mysql關(guān)閉的無(wú)效連接,導(dǎo)致業(yè)務(wù)出錯(cuò)的一種兜底掃描方案。
具體過(guò)程就是每隔keepaliveTime時(shí)間間隔,去和數(shù)據(jù)庫(kù)發(fā)送心跳,來(lái)探測(cè)連接是否有效。如果發(fā)現(xiàn)是無(wú)效的,就會(huì)及時(shí)從連接池中剔除,來(lái)保證業(yè)務(wù)進(jìn)程獲取到的都是有效連接。
如果配置了connectionTestQuery ,如 select 1, 心跳檢查過(guò)程就會(huì)調(diào)用connectionTestQuery。
所以如果你配置了connectionTestQuery 但是沒(méi)有配置keepaliveTime ,是沒(méi)有用的,因?yàn)槟J(rèn)是關(guān)閉的。
而connectionTestQuery 配置項(xiàng),官方建議如果驅(qū)動(dòng)支持JDBC4,不要設(shè)置此屬性!
因?yàn)橄啾扔谕ㄟ^(guò)select查詢方式探活,mysql 自帶的ping命令 性能更高(直接在sql server返回結(jié)果,就不會(huì)做語(yǔ)法解析,執(zhí)行優(yōu)化,再通過(guò)存儲(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)文章
聽(tīng)說(shuō)mysql中的join很慢?是你用的姿勢(shì)不對(duì)吧
這篇文章主要介紹了聽(tīng)說(shuō)mysql中的join很慢?是你用的姿勢(shì)不對(duì)吧,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
mysql使用字符串字段判斷是否包含某個(gè)字符串的方法
在MySQL中,判斷字符串字段是否包含特定子字符串,可使用LIKE操作符、INSTR()函數(shù)、LOCATE()函數(shù)、POSITION()函數(shù)、FIND_IN_SET()函數(shù)以及正則表達(dá)式REGEXP或RLIKE,每種方法適用于不同的場(chǎng)景和需求,LIKE和INSTR()通常用于簡(jiǎn)單包含判斷2024-09-09
MySQL中常用查看鎖和事務(wù)的SQL語(yǔ)句詳解
這篇文章主要介紹了MySQL中常用查看鎖和事務(wù)的SQL語(yǔ)句,用于查看鎖和事務(wù)的狀態(tài),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
使用innodb_force_recovery解決MySQL崩潰無(wú)法重啟問(wèn)題
這篇文章主要介紹了使用innodb_force_recovery解決MySQL崩潰無(wú)法重啟問(wèn)題,這只一個(gè)成功案例,并不是萬(wàn)能的解決方法,需要酌情考慮,需要的朋友可以參考下2015-05-05
mysql 鎖表鎖行語(yǔ)句分享(MySQL事務(wù)處理)
下面這個(gè)語(yǔ)句是鎖定一行數(shù)據(jù),開(kāi)始讀取,一直到刪除后都不會(huì)有第二個(gè)人也讀到這條數(shù)據(jù)2011-09-09
Mysql存儲(chǔ)過(guò)程和函數(shù)區(qū)別介紹
這篇文章主要介紹了Mysql存儲(chǔ)過(guò)程和函數(shù)的區(qū)別,需要的朋友可以參考下2014-03-03
MySQL?8.0?對(duì)?limit?的優(yōu)化技巧
從不同版本的 MySQL 發(fā)展軌跡來(lái)看 MySQL 的優(yōu)化器越來(lái)越智能 (比如大家期待已久的直方圖特性) ,能更多的減少人為干預(yù),提升執(zhí)行計(jì)劃的準(zhǔn)確性,這篇文章主要介紹了MySQL?8.0?對(duì)?limit?的優(yōu)化,需要的朋友可以參考下2022-10-10
mysql存儲(chǔ)過(guò)程之錯(cuò)誤處理實(shí)例詳解
這篇文章主要介紹了mysql存儲(chǔ)過(guò)程之錯(cuò)誤處理,結(jié)合實(shí)例形式詳細(xì)分析了mysql存儲(chǔ)過(guò)程錯(cuò)誤處理相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-12-12

