golang内部自带了连接池功能,刚开始接触golang的时候不了解这个,还自己搞了一个 sql.Open的对象管理池,真的非常囧
golang内部自带了连接池功能,刚开始接触golang的时候不了解这个,还自己搞了一个 sql.Open的对象管理池,真的非常囧啊。
sql.Open函数实际上是返回一个连接池对象,不是单个连接。在open的时候并没有去连接数据库,只有在执行query、exce方法的时候才会去实际连接数据库。在一个应用中同样的库连接只需要保存一个sql.Open之后的db对象就可以了,不需要多次open。
golang中关于mysql的增删改查我在前面的一篇文章中有说明了,不了解的小伙们可以先去了解一下:golang连接mysql操作示例增删改查
因为普通程序执行完毕之后资源就会被释放掉,所以这里尝试使用web服务进行演示。
开启web服务
首页先启动一个web服务监听9090端口,比较简单不多做说明。
func startHttpServer() { http.HandleFunc("/pool", pool) err := http.ListenAndServe(":9090", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } }
db对象初始化
声明一个全局的db对象,并进行初始化。
var db *sql.DB func init() { db, _ = sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/test?charset=utf8") db.SetMaxOpenConns(2000) db.SetMaxIdleConns(1000) db.Ping() }
连接池的实现关键在于SetMaxOpenConns和SetMaxIdleConns,其中:
SetMaxOpenConns用于设置最大打开的连接数,默认值为0表示不限制。
SetMaxIdleConns用于设置闲置的连接数。
设置最大的连接数,可以避免并发太高导致连接mysql出现too many connections的错误。设置闲置的连接数则当开启的一个连接使用完成后可以放在池里等候下一次使用。
请求方法
上面开启http请求设置了请求/pool地址的执行方法
func pool(w http.ResponseWriter, r *http.Request) { rows, err := db.Query("SELECT * FROM user limit 1") defer rows.Close() checkErr(err) columns, _ := rows.Columns() scanArgs := make([]interface{}, len(columns)) values := make([]interface{}, len(columns)) for j := range values { scanArgs[j] = &values[j] } record := make(map[string]string) for rows.Next() { //将行数据保存到record字典 err = rows.Scan(scanArgs...) for i, col := range values { if col != nil { record[columns[i]] = string(col.([]byte)) } } } fmt.Println(record) fmt.Fprintln(w, "finish") } func checkErr(err error) { if err != nil { fmt.Println(err) panic(err) } }
pool方法就是从user表中查出一条记录然后存放到map中,最后输出finish。代码到这里就算完了非常简单,下面来测试一下。首先启动http服务,然后使用ab进行并发测试访问:
$ ab -c 100 -n 1000 'http://localhost:9090/pool'
在数据库中通过show processlist查看连接进程:
golang数据库连接池
可以看到有100来个进程。
因为避免了重复创建连接,所以使用连接池可以很明显的提高性能。有兴趣的童靴可以去掉连接池代码自己测试一下。完整代码如下:
//数据库连接池测试 package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "log" "net/http" ) var db *sql.DB func init() { db, _ = sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/test?charset=utf8") db.SetMaxOpenConns(2000) db.SetMaxIdleConns(1000) db.Ping() } func main() { startHttpServer() } func startHttpServer() { http.HandleFunc("/pool", pool) err := http.ListenAndServe(":9090", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } func pool(w http.ResponseWriter, r *http.Request) { rows, err := db.Query("SELECT * FROM user limit 1") defer rows.Close() checkErr(err) columns, _ := rows.Columns() scanArgs := make([]interface{}, len(columns)) values := make([]interface{}, len(columns)) for j := range values { scanArgs[j] = &values[j] } record := make(map[string]string) for rows.Next() { //将行数据保存到record字典 err = rows.Scan(scanArgs...) for i, col := range values { if col != nil { record[columns[i]] = string(col.([]byte)) } } } fmt.Println(record) fmt.Fprintln(w, "finish") } func checkErr(err error) { if err != nil { fmt.Println(err) panic(err) } }
小结
golang这边实现的连接池只提供了SetMaxOpenConns和SetMaxIdleConns方法进行连接池方面的配置。在使用的过程中有一个问题就是数据库本身对连接有一个超时时间的设置,如果超时时间到了数据库会单方面断掉连接,此时再用连接池内的连接进行访问就会出错。
packets.go:32: unexpected EOF packets.go:118: write tcp 192.168.3.90:3306: broken pipe
上面都是错误都是go-sql-drive本身的输出,有的时候还会出现bad connection的错误。多请求几次后连接池会重新打开新连接这时候就没有问题了。关于这个问题自己有初步的解决方法,但是感觉不太完美,下次再放上来。
转载请注明:快乐编程 » golang go-sql-drive mysql连接池的实现

掌握添加MySQL用户的方法对于数据库管理员和开发者至关重要,因为它确保数据库的安全性和访问控制。1)使用CREATEUSER命令创建新用户,2)通过GRANT命令分配权限,3)使用FLUSHPRIVILEGES确保权限生效,4)定期审计和清理用户账户以维护性能和安全。

chosecharforfixed-lengthdata,varcharforvariable-lengthdata,andtextforlargetextfield.1)chariseffity forconsistent-lengthdatalikecodes.2)varcharsuitsvariable-lengthdatalikenames,ballancingflexibilitibility andperformance.3)

在MySQL中处理字符串数据类型和索引的最佳实践包括:1)选择合适的字符串类型,如CHAR用于固定长度,VARCHAR用于可变长度,TEXT用于大文本;2)谨慎索引,避免过度索引,针对常用查询创建索引;3)使用前缀索引和全文索引优化长字符串搜索;4)定期监控和优化索引,保持索引小巧高效。通过这些方法,可以在读取和写入性能之间取得平衡,提升数据库效率。

ToaddauserremotelytoMySQL,followthesesteps:1)ConnecttoMySQLasroot,2)Createanewuserwithremoteaccess,3)Grantnecessaryprivileges,and4)Flushprivileges.BecautiousofsecurityrisksbylimitingprivilegesandaccesstospecificIPs,ensuringstrongpasswords,andmonitori

tostorestringsefliceflicyInmySql,ChooSetherightDataTypeBasedyOrneOrneEds:1)USEcharforFixed-LengthStstringStringStringSlikeCountryCodes.2)UseVarcharforvariable-lengtthslikenames.3)USETEXTCONTENT.3)

选择MySQL的BLOB和TEXT数据类型时,BLOB适合存储二进制数据,TEXT适合存储文本数据。1)BLOB适用于图片、音频等二进制数据,2)TEXT适用于文章、评论等文本数据,选择时需考虑数据性质和性能优化。

No,youshouldnotusetherootuserinMySQLforyourproduct.Instead,createspecificuserswithlimitedprivilegestoenhancesecurityandperformance:1)Createanewuserwithastrongpassword,2)Grantonlynecessarypermissionstothisuser,3)Regularlyreviewandupdateuserpermissions

mySqlStringDatatatPessHouldBechoseBeadeDataCharacteristicsAndUsecases:1)USECHARFORFIXED LENGTHSTRINGSTRINGSLIKECOUNTRYCODES.2)USEDES.2)usevarcharforvariable-lengtthstringstringstringstringstringstringstringslikenames.3)usebinaryorvarrinaryorvarinarydatalbonydatalgebgeenfopical.4)


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。