mysql怎么设置超时时间

mysql怎么设置超时时间,第1张

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 的维护者们在后续版本更新时忘记更新文档吧。

FROM_UNIXTIME这个是MySQL函数而非PHP函数。在SQL语句中出现的函数都是MySQL函数。FROM_UNIXTIME(unix_timestamp) , FROM_UNIXTIME(unix_timestamp,format) 返回\'YYYY-MM-DD HH:MM:SS\'或YYYYMMDDHHMMSS 格式值的unix_timestamp参数表示,具体格式取决于该函数是否用在字符串中或是数字语境中。 若format 已经给出,则结果的格式是根据format 字符串而定。 format 可以包含同DATE_FORMAT() 函数输入项列表中相同的说明符。其实刚才的sql也可以这样写:[ol][*]SELECT * FROM table WHERE??FROM_UNIXTIME( time, \'%Y-%m-%d\' ) = \'2008-09-07\' [/ol]

你还在被以下问题困扰吗:

MySQL的安装规范中应该设置什么时区

JAVA应用读取到的时间和北京时间差了14个小时,为什么?怎么解决?

已经运行一段时间的业务,修改MySQL的时区会影响已经存储的时间类型数据吗?

迁移数据时会有导致时间类型数据时区错误的可能吗?

...

看完这篇文章,你能解决上面所有的疑惑。首先出场的是和时区相关的启动参数和系统变量。

如果要在 MySQL 启动时就指定时区,则应该使用启动参数: default-time-zone ,示例:

启动后我们可以看到控制时区的系统变量,其中 time_zone 变量控制时区,在MySQL运行时可以通过 set 命令修改(注意:不可以写在 my.cnf 中):

启动参数和系统变量的可用值遵循相同的格式:

system_time_zone 变量只有全局值没有会话值,不能动态修改,MySQL 启动时,将尝试自动确定服务器的时区,并使用它来设置 system_time_zone 系统变量, 此后该值不变。当 time_zone='system' 时,就是使用的这个时区,示例中 time_zone 就是 CST,而 CST 在 RedHat 上就是东八区:

概括一下就两点:

不仅是select now(),包括insert .. values(now())、以及字段的 DEFAULT CURRENT_TIMESTAMP 属性也受此影响:

timestamp 数据类型会存储当时session的时区信息,读取时会根据当前 session 的时区进行转换;而 datetime 数据类型插入的是什么值,再读取就是什么值,不受时区影响。也可以理解为已经存储的数据是不会变的,只是 timestamp 类型数据在读取时会根据时区转换:

关于时区所有明面上的东西都在上面了,我们前面提到的困扰就是在暗处的经验。

1. MySQL的安装规范中应该设置什么时区?

对于国内的业务了,在 my.cnf 写入 default-time-zone='+08:00' ,其他地区和开发确认取对应时区即可。

为什么不设置为 system 呢?使用系统时间看起来也是个不错的选择,比较省事。不建议的原因有两点:

2. JAVA应用读取到的时间和北京时间差了14个小时,为什么?怎么解决?

这通常是 JDBC 参数中没有为连接设置时区属性(用 serverTimezone 参数指定),并且MySQL中没有设置全局时区,这样MySQL默认使用的是系统时区,即 CST。这样一来应用与MySQL 建立的连接的 session time_zone 为 CST ,前面我们提到 CST 在 RedHat 上是 +08:00 时区,但其实它一共能代表4个时区:

JDBC在解析CST时使用了美国标准时间,这就会导致时区错误。要解决也简单:一是遵守上面刚说到的规范,对MySQL显式地设置'+08:00'时区;二是JDBC设置正确的 serverTimezone。

3. 已经运行一段时间的业务,修改MySQL的时区会影响已经存储的时间类型数据吗?

完全不会,只会影响对 timestamp 数据类型的读取。这里不得不提一句,为啥要用 timestamp?用 datetime 不香吗,范围更大,存储空间其实差别很小,赶紧加到开发规范中吧。

4. 迁移数据时会有导致时间类型数据时区错误的可能吗?

这个还真有。

如何避免?mysqldump 也提供了一个参数 --skip-tz-utc ,意思就是导出数据的那个连接不设置 UTC 时区,使用 MySQL 的 global time_zone 系统变量值。

其实 mysqldump 导出 sql 文件时默认也是使用 UTC 时区,并且会在导出的 sql 文件头部带有 session time_zone 信息,这样可以保证导 SQL 文件导入和导出时使用相同的时区,从而保证数据的时区正确(而导出的 csv 文件显然不可以携带此信息)。需要注意的是 --compact 参数会去掉 sql 文件的所有头信息,所以一定要记得: --compact 参数得和 --skip-tz-utc 一起使用。


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

原文地址: http://outofmemory.cn/zaji/8715980.html

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

发表评论

登录后才能评论

评论列表(0条)

保存