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

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

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

1.建立连接超时测试

下面例子中,设置连接超时时间为5s,读超时时间6s。

MySQL server IP是192.168.0.101,端口3306。

每3s执行一次SQL。

// simple.go

package main

import (
"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 error
DB, 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 int
err := 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 *Rows
var err error
for 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 DROP

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. mysql设置连接超时时间参数:wait_timeout

    [root@ ~]# mysql -h 192.168.0.* -uroot -pEnter password: Welcome to the MySQL monitor. Commands end ...

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

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

  3. 解决ssh连接超时时间(ssh timeout)的设置方法

    本文介绍下,linux中ssh连接超时时间的设置方法,以避免总是被强行退出.有需要的朋友,参考下吧.有关修改ssh连接超时时间的方法,网上介绍的很多了.比如下面这个:可以减少ssh连接超时等待的时间: ...

  4. nginx——优化 Nginx 连接超时时间

    1. 什么是连接超时 (1) 举个例子,某饭店请了服务员招待顾客,但是现在饭店不景气,因此要解雇掉一些服务员,这里的服务员就相当于 Nginx 服务建立的连接 (2) 当服务器建立的连接没有接收处理请 ...

  5. mysql和连接相关的timeout

    MySQL和连接相关的timeout 今天同事问为什么查询mysql库时, 在数据量比较大时,会话总断.刚开始以为是mysql的和连接有关timeout的问题,结果是网络的不稳定的原因. 下面总结下和 ...

  6. config文件中可以配置查询超时时间

    web.config配置数据库连接 第一种:获取连接字符串 首先要定义命名空间 system.configuration 1.  string connstr= string constr = Con ...

  7. Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionExcep linux下mysql修改连接超时wait_timeout修改后就ok了

    Linux下mysql修改连接超时wait_timeout 1,首先: show variables like '%timeout%': 显示结果: +------------------------ ...

  8. 转 HttpClient 设置连接超时时间

    要: HttpClient 4.5版本升级后,设置超时时间的API又有新的变化,请大家关注. HttpClient升级到4.5版本后,API有很多变化,HttpClient 4之后,API一直没有太稳 ...

  9. HttpClient设置连接超时时间

    https://www.cnblogs.com/winner-0715/p/7087591.html 使用HttpClient,一般都需要设置连接超时时间和获取数据超时时间.这两个参数很重要,目的是为 ...

随机推荐

  1. MySQL cmd操作

    1.开启关闭服务 net start mysql net stio mysql 2.登陆 在CMD命令窗口敲入命令 mysql -hlocalhost -uroot -p 后按回车(注意这里的&quo ...

  2. Servlet和JSP学习总结

    目录 Jsp会被编译成servlet,在页面被第一次访问的时候 Jsp中可以在html页面中嵌入java代码或者引入jsp标签 可以在html中引入自定义标签 Web工程的目录结构 Jsp的注释 Js ...

  3. Go测试开发就用这三板斧

    一个古老的面试问题:“给你个XX,你怎么测试?” 时间穿越到9102,Go语言成为了新生代的代名词.老问题变成了“给你Golang程序,你怎么测试?”     看完本文后,读者可以拍着胸脯回答,“一共 ...

  4. 区块链火爆,再不知道Golang就晚了

    Golang,也叫Go语言,是2009年刚刚被发发布的一门新语言. 区块链,是2019年我国提出的新战略. 一个不争的事实就是,大多数从事区块链开发的小伙伴都是用Golang,大多数招聘区块链技术工作 ...

  5. async 与 await

    async 关键字 1.含义:表示函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 2.定义与调用 async function hello (flag) { if (flag) { re ...

  6. python pip 出现locations that require TLS/SSL异常处理方法

    python pip 出现locations that require TLS/SSL异常处理方法 转载 郑才华 发布于2018-03-24 21:41:16 阅读数 51844 收藏 展开 最近在r ...

  7. 洛谷P3600随机数生成器——期望+DP

    原题链接 写到一半发现写不下去了... 所以orz xyz32768,您去看这篇题解吧,思路很清晰,我之前写的胡言乱语与之差距不啻天渊 #include <algorithm> #incl ...

  8. 题解 [CF332C] Students' Revenge

    题面 解析 辣鸡题面毁我青春 因为翻译的题面中写了一句\(剩下的n−k个不会完成\). 所以就以为剩下的\(n-k\)个都会算上不满意值. (然而事实是只有\(p-k\)个...) 首先根据主席的规则 ...

  9. 题解 [BZOJ1295][SCOI2009] 最长距离

    题面 解析 \(n\)只有\(30\)可以直接枚举每个矩形, 判断他们的左上角到右下角或右上角到左上角的最短路是否小于\(T\). 最短路可以用\(dijkstra\). 一开始想用\(DP\)写最短 ...

  10. 获取节点 document.getElementBy{Id,Name,TagName,ClassName

    document.getElementById(" "); document.getElementByName(" "); document.getElemen ...