如果不通过线路,您将不会知道连接的真实状态,并且SELECT 1
是一个足够好的候选者(可以说您可以提出一个更短的命令,它需要更少的时间来解析,但与网络甚至环回延迟相比,这些节省会微不足道。)
话虽如此,我认为在从池中检查连接之前ping 连接并不是最好的方法。
您可能应该简单地让您的连接池管理器强制执行其自己的保持活动(超时)策略,以避免被服务器断开连接(缺少更严重的干预连接问题,这可能会影响您在常规操作中间的打击 -并且您的连接池管理器无论如何都无法提供帮助),以及为了避免不必要地占用数据库(考虑文件句柄和内存使用)。
因此,在我看来,在从池中检查连接之前测试连接条件的真正价值是值得怀疑的。在将连接签入回池之前测试连接状态可能是值得的,但这可以通过在出现 SQL 硬错误(或等效异常)时简单地将连接标记为脏来隐式完成(除非您正在使用的 API 已经为您公开一个类似is-bad
的调用。)
因此,我建议:
- 实施客户端保活策略
- 从池中签出连接时不执行任何检查
- 在连接返回池之前执行脏检查
- 让应用程序代码处理其他(非超时)异常连接条件
更新
从您的评论中可以看出您真的很想ping 连接(我认为这是因为您无法完全控制或了解 MySQL 服务器上的超时特征或代理等网络设备)
在这种情况下,您可以DO 1
使用SELECT 1
; 它稍微快一点——解析时间更短,并且它不返回实际数据(尽管你会得到 TCP ack
,所以你仍然会进行往返验证连接是否仍然建立。)
更新 2
关于Joshua 的帖子,这里是各种场景的数据包捕获跟踪:
SELECT 1;
13:51:01.463112 IP client.45893 > server.mysql: P 2270604498:2270604511(13) ack 2531191393 win 1460 <nop,nop,timestamp 2983462950 59680547>
13:51:01.463682 IP server.mysql > client.45893: P 1:57(56) ack 13 win 65306 <nop,nop,timestamp 59680938 2983462950>
13:51:01.463698 IP client.45893 > server.mysql: . ack 57 win 1460 <nop,nop,timestamp 2983462951 59680938>
DO 1;
13:51:27.415520 IP client.45893 > server.mysql: P 13:22(9) ack 57 win 1460 <nop,nop,timestamp 2983488906 59680938>
13:51:27.415931 IP server.mysql > client.45893: P 57:68(11) ack 22 win 65297 <nop,nop,timestamp 59681197 2983488906>
13:51:27.415948 IP client.45893 > server.mysql: . ack 68 win 1460 <nop,nop,timestamp 2983488907 59681197>
mysql_ping
14:54:05.545860 IP client.46156 > server.mysql: P 69:74(5) ack 78 win 1460 <nop,nop,timestamp 2987247459 59718745>
14:54:05.546076 IP server.mysql > client.46156: P 78:89(11) ack 74 win 65462 <nop,nop,timestamp 59718776 2987247459>
14:54:05.546092 IP client.46156 > server.mysql: . ack 89 win 1460 <nop,nop,timestamp 2987247459 59718776>
如您所见,除了mysql_ping
数据包是 5 个字节而不是DO 1;
9 个字节这一事实之外,往返次数(因此,网络引起的延迟)完全相同。DO 1
与此相反,您支付的唯一额外成本mysql_ping
是解析DO 1
,这是微不足道的。