本文测试连接mysql的超时时间。

这里的“连接”是建立连接的意思。

连接mysql的超时时间是通过参数timeout设置的。

1.建立连接超时测试

下面例子中,设置连接超时时间为5s,读超时时间6s。
MySQL server IP是192.168.0.101,端口3306。

每3s执行一次SQL。

// simple.gopackage mainimport ("database/sql""log""time"_ "github.com/go-sql-driver/mysql"
)var DB *sql.DB
var dataBase = "root:Aa123456@tcp(192.168.0.101:3306)/?timeout=5s&readTimeout=6s"func mysqlInit() {var err errorDB, err = sql.Open("mysql", dataBase)if err != nil {log.Fatalln("open db fail:", err)}DB.SetMaxOpenConns(3)DB.SetMaxIdleConns(3)
}func main() {mysqlInit()for {log.Println("start")execSql()time.Sleep(3*time.Second)}
}func execSql() {var value interr := DB.QueryRow("select 1").Scan(&value)if err != nil {log.Println("query failed:", err)return}log.Println("value:", value)
}

启动程序:

go run simple.go

之后,接着在客户端使用iptables将所有发送到MySQL服务的数据包drop掉.

清除所有的过滤规则,防止干扰:

sudo iptables -F

设置drop策略:

sudo iptables -A OUTPUT -p tcp --dport 3306 -d 192.168.0.101 -j DROP

查看策略:

[root@localhost lanyang]# iptables -nxvL
Chain INPUT (policy ACCEPT 4 packets, 505 bytes)pkts      bytes target     prot opt in     out     source               destination         Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)pkts      bytes target     prot opt in     out     source               destination         Chain OUTPUT (policy ACCEPT 4 packets, 304 bytes)pkts      bytes target     prot opt in     out     source               destination         49     3025 DROP       tcp  --  *      *       0.0.0.0/0            192.168.0.101       tcp dpt:3306 

或者在MySQL上设置iptables规则,效果是一样的:

sudo iptables -A INPUT -p tcp --dport 3306 -d 192.168.0.101 -j DROP

这样就会触发重试机制,最后超时。

output:

2019/10/27 18:34:52 start
2019/10/27 18:34:52 value: 1
2019/10/27 18:34:55 start
2019/10/27 18:34:55 value: 1
2019/10/27 18:34:58 start
2019/10/27 18:34:58 value: 1
2019/10/27 18:35:01 start
[mysql] 2019/10/27 18:35:07 packets.go:36: read tcp 192.168.0.104:54462->192.168.0.101:3306: i/o timeout
2019/10/27 18:35:07 query failed: invalid connection
2019/10/27 18:35:10 start
[mysql] 2019/10/27 18:35:15 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:35:20 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
2019/10/27 18:35:20 query failed: driver: bad connection
2019/10/27 18:35:23 start
[mysql] 2019/10/27 18:35:28 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:35:33 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:35:38 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
2019/10/27 18:35:38 query failed: driver: bad connection
2019/10/27 18:35:41 start
[mysql] 2019/10/27 18:35:46 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:35:51 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:35:56 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
2019/10/27 18:35:56 query failed: driver: bad connection
2019/10/27 18:35:59 start
[mysql] 2019/10/27 18:36:04 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:36:09 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
[mysql] 2019/10/27 18:36:14 driver.go:81: net.Error from Dial()': dial tcp 192.168.0.101:3306: i/o timeout
2019/10/27 18:36:14 query failed: driver: bad connection

从输出结果可以看到,首先打印读超时错误,6s超时(即readTimeout):

2019/10/27 18:35:01 start
[mysql] 2019/10/27 18:35:07 packets.go:36: read tcp 192.168.0.104:54462->192.168.0.101:3306: i/o timeout
2019/10/27 18:35:07 query failed: invalid connection

接着,每次执行SQL,都有3条连接错误日志,表示建立连接时,会尝试3次,每次超时时间5s(即设置的timeout)。

这里就引出一个问题,为什么每次执行SQL时,会进行3次建立连接尝试呢?

查一下QueryRow底层实现代码:

func (db *DB) QueryRow(query string, args ...interface{}) *Row {return db.QueryRowContext(context.Background(), query, args...)
}func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {rows, err := db.QueryContext(ctx, query, args...)return &Row{rows: rows, err: err}
}// QueryContext executes a query that returns rows, typically a SELECT.
// The args are for any placeholder parameters in the query.
func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {var rows *Rowsvar err errorfor i := 0; i < maxBadConnRetries; i++ {rows, err = db.query(ctx, query, args, cachedOrNewConn)if err != driver.ErrBadConn {break}}if err == driver.ErrBadConn {return db.query(ctx, query, args, alwaysNewConn)}return rows, err
}

其中,maxBadConnRetries定义为2:

// maxBadConnRetries is the number of maximum retries if the driver returns
// driver.ErrBadConn to signal a broken connection before forcing a new
// connection to be opened.
const maxBadConnRetries = 2

当err是driver.ErrBadConn时,会尝试3次进行连接。这就是为什么刚才的日志中有3次连接错误。

2.reject测试

另外,如果在客户端使用iptables将所有发送到MySQL服务的数据包reject掉:

sudo iptables -A OUTPUT -p tcp --dport 3306 -d 192.168.0.101 -j REJECT
sudo iptables -nxvL
Chain INPUT (policy ACCEPT 5 packets, 515 bytes)pkts      bytes target     prot opt in     out     source               destination         Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)pkts      bytes target     prot opt in     out     source               destination         Chain OUTPUT (policy ACCEPT 4 packets, 372 bytes)pkts      bytes target     prot opt in     out     source               destination         4      260 REJECT     tcp  --  *      *       0.0.0.0/0            192.168.0.101      tcp dpt:3306 reject-with icmp-port-unreachable 

或者在MySQL上设置iptables规则,效果是一样的:

sudo iptables -A INPUT -p tcp --dport 3306 -d 192.168.0.101 -j REJECT

2.1 测试1:timeout=5s&readTimeout=6s

此时,
reject会直接返回RESET操作,将连接重置,不会触发连接建立超时时间。

日志输出:

2019/10/27 21:39:55 start
2019/10/27 21:39:55 value: 1
2019/10/27 21:39:58 start
2019/10/27 21:39:58 value: 1
2019/10/27 21:40:01 start
2019/10/27 21:40:01 value: 1
2019/10/27 21:40:04 start
2019/10/27 21:40:04 value: 1
2019/10/27 21:40:07 start
[mysql] 2019/10/27 21:40:13 packets.go:36: read tcp 192.168.0.104:54536->192.168.0.101:3306: i/o timeout
2019/10/27 21:40:13 query failed: invalid connection
2019/10/27 21:40:16 start
2019/10/27 21:40:17 query failed: dial tcp 192.168.0.101:3306: connect: connection refused
2019/10/27 21:40:20 start
2019/10/27 21:40:21 query failed: dial tcp 192.168.0.101:3306: connect: connection refused
2019/10/27 21:40:24 start
2019/10/27 21:40:25 query failed: dial tcp 192.168.0.101:3306: connect: connection refused
2019/10/27 21:40:28 start
2019/10/27 21:40:29 query failed: dial tcp 192.168.0.101:3306: connect: connection refused
2019/10/27 21:40:32 start
2019/10/27 21:40:33 query failed: dial tcp 192.168.0.101:3306: connect: connection refused

从输出中可以看到,首先打印读超时错误,读超时readTimeout设置为6s:

[mysql] 2019/10/27 21:40:13 packets.go:36: read tcp 192.168.0.104:54536->192.168.0.101:3306: i/o timeout

后续的日志,都是连接被reset,无法连接的错误。

2.2 测试2:timeout=1s&readTimeout=6s

在测试结果表现上,与测试1基本相同。
唯一不同的是,有时会触发i/o timeout。

因为测试2中设置的timeout是1s,比测试1中timeout 5s小。

日志输出:

2020/03/29 16:35:09 start
2020/03/29 16:35:09 value: 1
2020/03/29 16:35:12 start
2020/03/29 16:35:12 value: 1
2020/03/29 16:35:15 start
[mysql] 2020/03/29 16:35:21 packets.go:36: read tcp 192.168.1.107:49654->192.168.1.107:3306: i/o timeout
2020/03/29 16:35:21 query failed: invalid connection
2020/03/29 16:35:24 start
[mysql] 2020/03/29 16:35:25 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:35:26 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:35:26 query failed: driver: bad connection
2020/03/29 16:35:29 start
2020/03/29 16:35:30 query failed: dial tcp 192.168.1.107:3306: connect: connection refused
2020/03/29 16:35:33 start
2020/03/29 16:35:34 query failed: dial tcp 192.168.1.107:3306: connect: connection refused
2020/03/29 16:35:37 start
2020/03/29 16:35:38 query failed: dial tcp 192.168.1.107:3306: connect: connection refused
2020/03/29 16:35:41 start
[mysql] 2020/03/29 16:35:42 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:35:43 query failed: dial tcp 192.168.1.107:3306: connect: connection refused
2020/03/29 16:35:46 start
[mysql] 2020/03/29 16:35:47 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:35:48 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:35:49 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:35:49 query failed: driver: bad connection
2020/03/29 16:35:52 start
[mysql] 2020/03/29 16:35:53 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:35:54 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:35:55 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:35:55 query failed: driver: bad connection
2020/03/29 16:35:58 start
[mysql] 2020/03/29 16:35:59 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:36:00 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:36:01 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:36:01 query failed: driver: bad connection
2020/03/29 16:36:04 start
[mysql] 2020/03/29 16:36:05 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:36:06 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:36:07 query failed: dial tcp 192.168.1.107:3306: connect: connection refused
2020/03/29 16:36:10 start
[mysql] 2020/03/29 16:36:11 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:36:12 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:36:13 query failed: dial tcp 192.168.1.107:3306: connect: connection refused
2020/03/29 16:36:16 start
[mysql] 2020/03/29 16:36:17 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:36:18 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
[mysql] 2020/03/29 16:36:19 driver.go:81: net.Error from Dial()': dial tcp 192.168.1.107:3306: i/o timeout
2020/03/29 16:36:19 query failed: driver: bad connection

3.参考

golang database sql DSN (Data Source Name)中的timeout, readTimeout

go-sql-driver/mysql

golang中mysql建立连接超时时间timeout 测试相关推荐

  1. golang mysql 超时_golang中mysql建立连接超时时间timeout 测试

    本文测试连接mysql的超时时间. 这里的"连接"是建立连接的意思. 连接mysql的超时时间是通过参数timeout设置的. 1.建立连接超时测试 下面例子中,设置连接超时时间为 ...

  2. mysql课程设计案例_JAVA中MySQL建立连接

    下面是在JAVA中与MySQL建立连接的一个模块: package com.han; import java.sql.Connection; import java.sql.DriverManager ...

  3. hibernate3连接mysql8报错_MySQL的8小时连接超时时间,导致系统过夜即崩溃,报错Could not roll back Hibernate transaction...

    2014年3月开始给单位开发<机关规范化管理网络平台>,10月底成功上线运行,但是存在一个bug: 部署环境: apache tomcat 6.0.41 + mysql5.5 + jbpm ...

  4. linux socket默认超时时间设置,Socket中如何设置连接超时 (转)

    Socket中如何设置连接超时 (转) Socket中如何设置连接超时 AntGhazi/2001.12.14 主页:antghazi.yeah 把CSDN与中文翻了底朝天,也没找到如何设置socke ...

  5. 连接mysql超时时间设置多少_怎么设置数据库的连接数和连接超时时间

    如何设置数据库的连接数和连接超时时间 连接数的话可以修改spfile文件来约束 查看当前的连接数: select count(*) from v$process; –数据库允许的最大连接数: sele ...

  6. Java两则故障分析和常见连接超时时间

    郑昀 汇总 20130309 常见现象的故障分析: 现象倒推一:Java Web应用的连接数暴增 最大的可能是,Web应用的线程调用路径中阻塞在某个远端资源上. 线程向某个远端资源发起的请求被阻塞,可 ...

  7. 网页 服务器长连接超时时间,服务器设置长连接超时时间

    服务器设置长连接超时时间 内容精选 换一换 有以下几种现象:将制作好的SD卡插入开发者板并上电后,开发者板LED1与LED2灯状态信息异常.将制作好的SD卡插入开发者板,并通过USB方式连接Ubunt ...

  8. 如何控制C#Socket的连接超时时间

    最近在Socket编程的时候发现只能设置Send和Recieve的Timeout时间,而Connect方法的Timeout是固定的,大概有30-40s,如果用同步方法界面会卡死很长时间 下面介绍两种通 ...

  9. httpclient: 设置请求的超时时间,连接超时时间等

    1.为什么要设置HTTP timeout? 1.与用户操作相关的接口,如果不设置超时时间,将会出现长时间的无响应,严重影响用户体验. 2.负载很高的系统,因为大量调用耗时长的接口,导致性能急剧下降,从 ...

最新文章

  1. android系统底层驱动多个物理按键上报同一个键值给app层,app层如何区分
  2. TF之DD:利用Inception模型+GD算法生成带背景的大尺寸、高质量的Deep Dream图片——五个架构设计思维导图
  3. Element-ui导航组件NavMenu导航高亮设置
  4. 用汇编的眼光看C++(之指针2)
  5. 工作——常用语法记录
  6. win11快捷键怎么使用 Windows11快捷键的使用方法
  7. docker-maven-plugin 推送镜像到 docker-hub
  8. OSG加载DEM高程数据
  9. 基于STM32通过RTC唤醒低功耗模式
  10. 综合项目之闪讯破解(一)之 闪讯拨号用户名核心算法
  11. ucfirst() 把字符串中的首字符转换为大写
  12. 【转】推荐几个免费下载破解软件的网站以及系统
  13. html制作横向菜单,CSS 横向菜单的制作
  14. 东华OJ基础85——手机短号
  15. FPGA有哪些优质的带源码的IP开源网站?
  16. 使用Flutter开发的抖音国际版
  17. 半导体基本知识 PN结的形成及特性
  18. 定制自己的报表!7款实用开源报表工具
  19. macOS: 字体(font)文件 的 存放路径
  20. python列表中的索引问题:从左到右由0开始;从右到左由-1开始

热门文章

  1. 关于python UI Selenium自动化的一个浏览器driver重复调用问题
  2. easyui textbox添加失去焦点事件
  3. SuSE Linux企业版简介
  4. 人肉云-【软件和信息服务】2014.02
  5. 【100%通过率】华为OD机试真题 C++ 实现【积木最远距离】【2022.11 Q4 新题】
  6. 文件上传漏洞防范措施
  7. Option PE header
  8. 【课程作业】科学研究方法与论文写作
  9. 配资指数带您了解恒生HOMS系统发展历史
  10. H5开发的移动应用打开高德地图、百度地图