不,连接字符串无法启动你的 VPN 隧道
VPN 归操作系统或客户端所有,绝不属于驱动。先建好隧道,再用 netonly 传递域凭据,最后检查游标的往返次数。
开发者一直在找那个位置:某条连接字符串、某个 JDBC URL 或某条 tnsnames.ora 记录在里面选择 VPN。这样的位置并不存在。隧道由操作系统或注册虚拟网卡的厂商客户端建立,其上每一层数据库库都使用由此产生的套接字层。连接字符串只说明主机、端口和凭据,这就是它的全部词汇。
误区:连接字符串可以选择隧道
驱动向主机和端口打开 TCP 套接字。它没有建立隧道的 API,没有隧道配置文件的字段,也没有向 VPN 网关认证的手段。
这就是为什么一旦路由存在,各种工具的行为完全一致。SSMS、DBeaver、Eclipse Data Tools 和普通的 sqlcmd 都表现得像服务器在本地网络上一样,因为从套接字的角度看确实如此。虚拟网卡让数据库子网变得可达,而驱动从不知道这是怎么做到的。
这也解释了为什么连接字符串修不好掉线的隧道。链路断开时,驱动报告超时或一般网络错误,而把它当作查询问题的应用代码会永远重试错误的那一层。
在驱动运行之前先把隧道建起来
按照服务商或网络团队的说明,在操作系统层面连接 VPN,然后再打开工具。实践中这意味着在驱动解析主机名之前,通往数据库子网的路由就已经存在。
把隧道的监护放在应用之外. 由 PHP 或 Java 服务自己去建链路,等于把某家服务商的行为写进业务代码,每次故障切换都变成一次应用发版。而由监护程序持有隧道、监视它并重启它,是与查询路径分开的另一件事。
在责怪驱动之前先检查路由。如果主机名解析不了,或者从 shell 里端口不应答,任何连接字符串都改变不了这一点。
误区:Windows 认证失败意味着路由坏了
跨 VPN 的 Windows 认证经常失败,报错看起来像网络故障,而路由其实是好的。当账户属于另一个域、笔记本又加不进去时,请用显式凭据启动客户端,而不是用桌面会话的身份。
runas /noprofile /netonly /user:CORP\dbreader "C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Ssms.exe"/netonly 开关只把这些凭据用于远程认证。用 SELECT SUSER_SNAME() 确认服务器实际收到的是什么,而不要相信连接对话框。据说把服务器地址的凭据存进 Windows 凭据管理器对 SSMS 有效,但对以另一个账户运行的服务并不总是有效,所以在更改登录方式之前先确认进程用的是哪个身份。
延迟会把服务器端游标变成超时
服务器端游标让数据库保留结果并逐步取回,这把一个大结果变成许多小的往返。在局域网里这很便宜。经过一条增加几十毫秒延迟的隧道时,同一条查询可能在几乎没传多少数据的情况下就超过命令超时。
改用客户端游标,或者调大取数大小并把行分批,往返次数就会下降。瓶颈是交换次数,而不是链路标称速度,所以测吞吐量会误导你,测往返次数则不会。要用用户实际拉取的最大结果集来测,而不是用立刻返回的单行查询。如果超时只是位置移动而没有消失,就同时调大命令超时和取数大小再测一次。
同样的算术适用于话多的 ORM,以及任何按行发一条语句的客户端。如果查询计划没问题、传输量也小,那么在调数据库之前先数一数网络交换次数。
检查端口、实例和本地过滤
命名实例监听动态端口,所以要确认端口,而不是假定 1433。对默认实例,该值可以从该实例 SuperSocketNetLib 键下的 TcpPort 注册表值读出。对 Oracle,要确认 tnsnames.ora 里的主机名能解析、地址有应答、监听端口被允许;1521 只是常见默认值,不是保证。
然后要排除隧道自身的访问列表,最后再排除本机杀毒软件或主机防火墙——即使客户端和服务器是同一台机器,它们也可能拦住连接。在改配置之前先记下失败发生在哪一步,因为名称解析、TCP 可达性、以及 TLS 或登录,各自会用不同的报错失败。
把这一步写进工单。否则下一个人会重走一遍当初引发这一切的连接字符串搜索。