你不经过线路就不会知道连接的真实状态,SELECT 1 是一个足够好的候选者(可以说你可以想出一个更短的命令,花费更少的时间解析,但与网络甚至环回延迟相比,这些节省是微不足道的。)
话虽如此,我认为在从池中检查连接之前ping 连接并不是最好的方法。
您可能应该简单地让您的连接池管理器强制执行其自己的保持活动(超时)策略以避免被服务器断开连接(没有更严重的干预连接问题,这可能会影响您无论如何都要在常规操作中进行操作——而且您的连接池管理器无论如何都无法提供帮助),以及为了不占用数据库(想想文件句柄和内存使用) .
因此,在我看来,在从池中检查连接之前测试连接条件的真正价值是值得怀疑的。 在将连接检入回池之前可能值得测试连接状态,但这可以通过在出现 SQL 硬错误(或等效异常)时简单地将连接标记为脏来隐式完成(除非您使用的 API 已经为您公开了类似 is-bad 的调用。)
因此我建议:
- 实施客户端保活策略
- 从池中检出连接时不执行任何检查
- 在连接返回池之前执行脏检查
- 让应用程序代码处理其他(非超时)异常连接条件
更新
从您的 cmets 看来,您真的真的想要 ping 连接(我认为这是因为您没有完全控制或了解 MySQL 服务器上的超时特征或介入网络设备,例如代理等)
在这种情况下,您可以使用DO 1 作为SELECT 1 的替代品;它略微更快——解析时间更短,并且它不返回实际数据(尽管您将获得 TCP acks,因此您仍将进行往返验证连接是否仍然建立。)
更新 2
关于Joshua's post,以下是各种场景的抓包跟踪:
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 个字节这一事实之外,往返次数(因此,网络引起的延迟)完全相同。与mysql_ping 相比,您使用DO 1 支付的唯一额外费用是解析DO 1,这是微不足道的。