C#连接mysql数据库,怎么设置超时时间

C#连接mysql数据库,怎么设置超时时间,第1张

MySQL查询超时的设置方法

为了优化OceanBase的query timeout设置方式,特调研MySQL关于timeout的处理,记录如下。

[plain]

mysql>show variables like '%time%'

+----------------------------+-------------------+

| Variable_name | Value |

+----------------------------+-------------------+

| connect_timeout| 10|

| datetime_format| %Y-%m-%d %H:%i:%s |

| delayed_insert_timeout | 300 |

| flush_time | 1800 |

| innodb_lock_wait_timeout | 50|

| innodb_old_blocks_time | 0 |

| innodb_rollback_on_timeout | OFF |

| interactive_timeout| 28800 |

| lc_time_names | en_US |

| lock_wait_timeout | 31536000 |

| long_query_time| 10.000000 |

| net_read_timeout | 30|

| net_write_timeout | 60|

| slave_net_timeout | 3600 |

| slow_launch_time | 2 |

| system_time_zone | |

| time_format| %H:%i:%s |

| time_zone | SYSTEM|

| timed_mutexes | OFF |

| timestamp | 1366027807|

| wait_timeout | 28800 |

+----------------------------+-------------------+

21 rows in set, 1 warning (0.00 sec)

重点解释其中几个参数

connect_timeout:

The number of seconds that the mysqld server waits for a connect packet before respondingwith Bad handshake. The default value is 10 seconds as of MySQL 5.1.23 and 5 seconds before that. Increasing the connect_timeout value might help if clients frequently encounter errors of the form Lost connection to MySQL server at ‘XXX’, system error: errno.

解释:在获取链接时,等待握手的超时时间,只在登录时有效,登录成功这个参数就不管事了。主要是为了防止网络不佳时应用重连导致连接数涨太快,一般默认即可。

interactive_timeout:

The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect(). See alsowait_timeout.

解释:一个持续SLEEP状态的线程多久被关闭。线程每次被使用都会被唤醒为acrivity状态,执行完Query后成为interactive状态,重新开始计时。wait_timeout不同在于只作用于TCP/IP和Socket链接的线程,意义是一样的。

MySQL可以配置连接的超时时间,这个时间如果做得太长,甚至到了10min,那么很可能发生这种情况,3000个链接都被占满而且sleep在哪,新链接进不来,导致无法正常服务。因此这个配置尽量配置一个符合逻辑的值,60s或者120s等等。

说人话:

命令行下面敲一个命令后,直至下一个命令到来之前的时间间隔为interactive_time,如果这个时间间隔超过了interactive_timeout,则连接会被自动断开,下一个命令失败。不过一般的mysql客户端都有自动重连机制,下一个命令会在重连后执行。

[sql]

mysql>set interactive_timeout = 1

Query OK, 0 rows affected (0.00 sec)

mysql>show session variables like '%timeout%'

+----------------------------+----------+

| Variable_name | Value|

+----------------------------+----------+

| connect_timeout| 10 |

| interactive_timeout| 1|

| wait_timeout | 28800|

+----------------------------+----------+

10 rows in set (0.00 sec)

=====

[sql]

mysql>set wait_timeout = 1

Query OK, 0 rows affected (0.00 sec)

【去泡杯茶,等会儿】

mysql>show session variables like '%timeout%'

ERROR 2006 (HY000): MySQL server has gone away

No connection. Trying to reconnect...

Connection id:7

Current database: *** NONE ***

+----------------------------+----------+

| Variable_name | Value|

+----------------------------+----------+

| connect_timeout| 10 |

| interactive_timeout| 28800|

| wait_timeout | 28800|

+----------------------------+----------+

10 rows in set (0.01 sec)

wait_timeout:

The number of seconds the server waits for activity on a noninteractive connection (连接上没有活动命令,可能是客户端喝咖啡去了。)before closing it. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory.

On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client

这里顺带解释一下什么是non-interactive connection

>Non-Interactive Commands

Just do a quick look up on a table without logging into the client, running the query then logging back out again.

You can instead just type one line using the ' -e ' flag.

[sql]

c:\mysql\bin\mysql -u admin -p myDatabase -e 'SELECT * FROM employee'

net_read_timeout / net_write_timeout

The number of seconds to wait for more data from a connection before aborting the read. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory. 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. See also slave_net_timeout.

On Linux, the NO_ALARM build flag affects timeout behavior as indicated in the description of the net_retry_count system variable.

解释:这个参数只对TCP/IP链接有效,分别是数据库等待接收客户端发送网络包和发送网络包给客户端的超时时间,这是在Activity状态下的线程才有效的参数

JDBC setQueryTimeout函数:

为了避免查询出现死循环,或时间过长等现象,而导致线程阻塞,在获得Statement的实例后,stmt.setQueryTimeout(10)避免因为查询导致程序出现线程阻塞。

但昨天发现程序出现了,“ORA-01013: 用户请求取消当前的 *** 作”的异常。手工执行出错SQL语句发现,这个语句耗时20多秒。因为setQueryTimeout(10),所以还没有执行完查询语句就抛出异常了。使用setQueryTimeout(10)时一定要把时间设置的长一些,如60秒以上。只要不导致线程长期阻塞,就可以。太短了容易抛出,“ORA-01013: 用户请求取消当前的 *** 作”的异常

JDBC实现setQueryTimeout的原理:

[java]

class IfxCancelQueryImpl extends TimerTask

implements IfmxCancelQuery

{

IfxStatement stmt

Timer t = null

public void startCancel(IfxStatement paramIfxStatement, int paramInt)

throws Exception

{

this.stmt = paramIfxStatement

this.t = new Timer(true)

this.t.schedule(this, paramInt * 1000)

}

public void run()

{

try

{

this.stmt.cancel()

this.t.cancel()

}

catch (SQLException localSQLException)

{

this.t.cancel()

throw new Error(localSQLException.getErrorCode() + ":" + localSQLException.getMessage())

}

}

}

MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客户端中用来设置读取超时时间的参数。在 MySQL 的官方文档中,该参数的描述是这样的:

MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt to read from the server. There are retries if necessary, so the total effective timeout value is three times the option value. You can set the value so that a lost connection can be detected earlier than the TCP/IPClose_Wait_Timeout value of 10 minutes.

也就是说在需要的时候,实际的超时时间会是设定值的 3 倍。但是实际测试后发现实际的超时时间和设置的超时时间一致。

而具体什么时候发生三倍超时,在文档中没有找到。所以对 MySQL 5.7.20 的源码进行了一些分析。

使用 GDB 调试代码找了实际与 mysql server 通信的代码,如下:

请点击输入图片描述

其中 vio_read() 函数中,使用 recv 和 poll 来读取报文和做读取超时。net_should_retry() 函数只有在发生 EINTR 时才会返回 true。从这段代码来看是符合测试结果的,并没有对读取进行三次重试。只有在读取 *** 作被系统中断打断时才会重试,但是这个重试并没有次数限制。

从上面代码的分析可以看出,代码的逻辑和文档的描述不符。于是在一顿搜索后,找到了一个 MySQL 的 BUG(Bug #31163)。该 BUG 报告了在 MySQL 5.0 中,MySQL c api 读取的实际超时时间是设置的三倍,与现有文档描述相符。于是对 MySQL 5.0.96 的代码又进行分析。

同样使用 GDB 找到了通信部分的代码。这次找到了重试三次的代码,如下:

请点击输入图片描述

这个版本的 MySQL api 的读写超时是直接使用的 setsockopt 设置的。第一次循环,在 A 点发生了第一次超时(虽然注释写的非阻塞,但是客户端的连接始终是阻塞模式的)。然后在 B 点将该 socket 设置为阻塞模式,C 点这里重置 retry 次数。由于设置了 alarm 第二次以后的循环会直接进入 D 点的这个分支,并且判断循环次数。作为客户端时net->retry_count 始终是 1,所以重试了两次,共计进行了 3 次 vioread 后从 E 点退出函数。

由上面的分析可知,MySQL 文档对于该参数的描述已经过时,现在的 MYSQL_OPT_READ_TIMEOUT 并不会出现三倍超时的问题。而 Bug #31163 中的处理结果也是将文档中该参数的描述更新为实际读取超时时间是设定时间的三倍。也许是 MySQL 的维护者们在后续版本更新时忘记更新文档吧。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9902095.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存