golang 原生database\sql 的重連機(jī)制實(shí)現(xiàn)
1. 連接池的自動(dòng)管理
Go 的 database/sql 包確實(shí)有部分自動(dòng)重連能力,但有限制:
? 支持的情況
連接失效自動(dòng)重試
- 如果驅(qū)動(dòng)返回
ErrBadConn,database/sql會(huì)自動(dòng)重試操作 - 連接池會(huì)自動(dòng)檢測并移除失效的連接
- 下次使用時(shí),會(huì)從連接池獲取新連接(如果連接池中有可用連接)
- 如果驅(qū)動(dòng)返回
連接池自動(dòng)補(bǔ)充
- 當(dāng)連接池中的連接失效時(shí),會(huì)在需要時(shí)自動(dòng)創(chuàng)建新連接
- 只要
sql.DB對(duì)象沒有被關(guān)閉,連接池會(huì)持續(xù)工作
? 不支持的情況
整個(gè)連接池被關(guān)閉
- 如果調(diào)用了
db.Close(),整個(gè)連接池被關(guān)閉 - 不會(huì)自動(dòng)重新打開,需要重新創(chuàng)建
sql.DB對(duì)象
- 如果調(diào)用了
長時(shí)間停機(jī)后的恢復(fù)
- 如果 MySQL 停機(jī)時(shí)間很長,連接池中的所有連接都可能失效
- 雖然連接池會(huì)嘗試創(chuàng)建新連接,但沒有主動(dòng)的健康檢查
- 只有在實(shí)際使用時(shí)才會(huì)發(fā)現(xiàn)連接失效并重試
2. 實(shí)際場景分析
場景1: MySQL 短暫停機(jī)(幾秒到幾分鐘)
// 程序已連接
db, _ := sql.Open("mysql", "dsn...")
// MySQL 停機(jī)
// ... MySQL 重啟 ...
// 下次使用時(shí)
rows, err := db.Query("SELECT * FROM users")
// ? 可能成功:如果連接池中有可用連接,會(huì)自動(dòng)重試
// ?? 可能失?。喝绻羞B接都失效,需要等待重試或手動(dòng)處理
行為:
database/sql會(huì)檢測到連接失效(返回ErrBadConn)- 自動(dòng)重試操作,嘗試從連接池獲取新連接
- 如果連接池中有可用連接,會(huì)成功
- 如果所有連接都失效,會(huì)創(chuàng)建新連接
場景2: MySQL 長時(shí)間停機(jī)(幾分鐘到幾小時(shí))
// 程序已連接
db, _ := sql.Open("mysql", "dsn...")
// MySQL 長時(shí)間停機(jī)
// ... 所有連接都失效 ...
// MySQL 重啟后
rows, err := db.Query("SELECT * FROM users")
// ?? 第一次調(diào)用可能失敗,需要重試
// ? 后續(xù)調(diào)用會(huì)成功(連接池已恢復(fù))
行為:
- 連接池中的所有連接都已失效
- 第一次調(diào)用時(shí),會(huì)嘗試使用失效的連接,失敗
database/sql檢測到ErrBadConn,自動(dòng)重試- 重試時(shí)會(huì)創(chuàng)建新連接,成功
場景3: 調(diào)用 db.Close() 后
// 程序已連接
db, _ := sql.Open("mysql", "dsn...")
// 關(guān)閉連接池
db.Close()
// 嘗試使用
rows, err := db.Query("SELECT * FROM users")
// ? 失敗:sql: database is closed
// ? 不會(huì)自動(dòng)重連,需要重新創(chuàng)建 sql.DB 對(duì)象
行為:
sql.DB對(duì)象被標(biāo)記為已關(guān)閉- 所有操作都會(huì)返回
sql: database is closed錯(cuò)誤 - 不會(huì)自動(dòng)重新打開
實(shí)際使用建議
1. 對(duì)于 MySQL 短暫停機(jī)
原生機(jī)制通常足夠:
db, _ := sql.Open("mysql", "dsn...")
// 不需要特殊處理,database/sql 會(huì)自動(dòng)處理連接失效
2. 對(duì)于 MySQL 長時(shí)間停機(jī)
建議添加重試邏輯:
db, _ := sql.Open("mysql", "dsn...")
// 添加重試邏輯
var rows *sql.Rows
var err error
for i := 0; i < 3; i++ {
rows, err = db.Query("SELECT * FROM users")
if err == nil {
break
}
time.Sleep(time.Second)
}
3. 對(duì)于需要 Close() 的場景
原生機(jī)制不支持:
db.Close() // ? 無法恢復(fù),需要重新創(chuàng)建
總結(jié)
database/sql 原生機(jī)制:
- ? 處理連接失效和自動(dòng)重試
- ? 連接池自動(dòng)管理
- ? 不支持 Close() 后恢復(fù)
- ? 沒有主動(dòng)健康檢查
到此這篇關(guān)于golang 原生database\sql 的重連機(jī)制實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)golang 重連機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
對(duì)Golang中的FORM相關(guān)字段理解
這篇文章主要介紹了對(duì)Golang中的FORM相關(guān)字段理解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-05-05
go函數(shù)的參數(shù)設(shè)置默認(rèn)值的方法
Go語言不直接支持函數(shù)參數(shù)默認(rèn)值,但可以通過指針、結(jié)構(gòu)體、變長參數(shù)和選項(xiàng)模式等方法模擬,下面給大家分享幾種方式模擬函數(shù)參數(shù)的默認(rèn)值功能,感興趣的朋友一起看看吧2025-01-01
Golang哈希算法實(shí)現(xiàn)配置文件的監(jiān)控功能詳解
這篇文章主要介紹了Golang哈希算法實(shí)現(xiàn)配置文件的監(jiān)控功能,哈希和加密類似,唯一區(qū)別是哈希是單項(xiàng)的,即哈希后的數(shù)據(jù)無法解密,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
Go?內(nèi)聯(lián)優(yōu)化讓程序員愛不釋手
這篇文章主要介紹了Go?內(nèi)聯(lián)優(yōu)化讓程序員愛不釋手,內(nèi)聯(lián)是在編譯過程中自動(dòng)進(jìn)行的一類基本優(yōu)化之一,文章圍繞主題展開更多詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06
Golang中urlencode與urldecode編碼解碼詳解
這篇文章主要給大家介紹了關(guān)于Golang中urlencode與urldecode編碼解碼的相關(guān)資料,在Go語言中轉(zhuǎn)碼操作非常方便,可以使用內(nèi)置的encoding包來快速完成轉(zhuǎn)碼操作,Go語言中的encoding包提供了許多常用的編碼解碼方式,需要的朋友可以參考下2023-09-09

