根本原因是Linux版SQL Server空闲连接被中间网络设备或内核TCP栈主动关闭,Navicat默认不发保活探测;需同时设置“保持连接间隔”为30秒、勾选“使用keep alive”,并调优宿主机tcp_keepalive_time=600等参数。

Navicat 连接 Linux 平台的 SQL Server 2019 频繁断连,根本原因不是 Navicat 本身不稳定,而是 TCP 连接在空闲时被中间网络设备或 SQL Server 自身主动关闭,而 Navicat 默认不发保活探测。Linux 上的 SQL Server(尤其是容器部署)对连接空闲超时更敏感,且缺乏 Windows 环境下常见的 SQL Server Browser 服务辅助协调,问题更容易暴露。
SQL Server on Linux 的 idle connection timeout 行为
Linux 版 SQL Server 不读取 Windows 注册表中的 user connections 或 remote login timeout,它依赖底层 TCP 栈和自身配置。关键点:
- 没有等效于 Windows 上
sp_configure 'user options'的全局空闲超时设置 - 实际生效的是 Linux 内核的
tcp_fin_timeout和 SQL Server 自身的连接池/会话生命周期管理 - 容器中运行时,若未挂载持久化日志或未调优
sysctl参数,net.ipv4.tcp_keepalive_time默认值(7200 秒 = 2 小时)远高于常见防火墙/NAT 设备的清理阈值(通常 300–1800 秒) - 所以你看到的“突然断连”,大概率是连接在空闲 5–30 分钟后被路由器、云平台安全组或宿主机 iptables 清掉,SQL Server 甚至没收到 FIN 包,只等到下次读写时才发现连接已失效
Navicat “保持连接间隔” 设置为何常失效
这个选项(位于连接 → 高级 → 保持连接间隔)本质是 Navicat 主动执行 SELECT 1 类探针语句,但它有明确局限:
- 仅在已有活跃连接且无正在执行的查询时才触发,如果 Navicat 正在执行长事务或卡在 UI 等待响应,该机制完全不启动
- 若 SQL Server 因资源紧张无法及时响应
SELECT 1,Navicat 可能直接报错而非重试 - 勾选“使用 keep alive”后,实际启用的是操作系统级 TCP keepalive,但 Linux 容器默认继承宿主机参数,往往未覆盖为更激进的值(如
tcp_keepalive_time=600)
建议操作:
- 将“保持连接间隔”设为
30(单位:秒),而非默认0或60 - 必须同时勾选“使用 keep alive”
- 在宿主机(非容器内)执行以下命令临时调优(重启后失效):
sudo sysctl -w net.ipv4.tcp_keepalive_time=600 sudo sysctl -w net.ipv4.tcp_keepalive_intvl=60 sudo sysctl -w net.ipv4.tcp_keepalive_probes=3
- 若用 Docker,应在
docker run中加--sysctl参数持久化,例如:--sysctl net.ipv4.tcp_keepalive_time=600
Linux SQL Server 容器的日志与 errorlog 里藏了什么线索
断连发生后,第一手证据在 /var/opt/mssql/log/errorlog —— 不是 SQL Server 错误日志,而是连接被重置的底层痕迹:
- 出现
TDS: Client disconnected或Connection was closed by the client:说明客户端(Navicat 所在机器)TCP 层先断开,可能是本地防火墙或 NAT 超时 - 出现
Session is dead或Login failed for user后紧跟Reason: An error occurred while evaluating the password:大概率是连接复用时凭据缓存失效,源于连接池混用或 Kerberos 票据过期(Linux 上较少见,但启用了 AD 集成时需注意) - 出现大量
Failed to authenticate+NT AUTHORITY\ANONYMOUS LOGON:说明 Navicat 尝试 Windows 身份验证失败后 fallback 到 SQL 账户,但中间发生了重定向或协议协商失败
查看方式(容器内):
sudo docker exec -it <container_id> bash -c "tail -20 /var/opt/mssql/log/errorlog"注意:该文件是 UTF-16 编码,
cat 可能显示乱码,优先用 iconv -f UTF-16 -t UTF-8 /var/opt/mssql/log/errorlog | tail -20用 Test-NetConnection 或 telnet 验证的其实是假阳性
在 Windows 客户端上跑 Test-NetConnection your-linux-sql-ip -Port 1433 返回 TcpTestSucceeded : True,只能证明三层 IP+端口可达,完全不能反映四层 TCP 连接是否稳定。
真正要测的是“长连接保活能力”:
- 在 Navicat 连接成功后,立刻在 Linux 服务器上运行:
sudo ss -tnp | grep :1433 | grep ESTAB,记下对应连接的 inode 号 - 等待 5 分钟(不操作 Navicat),再次运行该命令,看同一 inode 是否消失
- 如果消失,再查
sudo journalctl -u mssql-server --since "5 minutes ago" | grep -i "disconnect|reset|timeout"
这比反复重连更有诊断价值。很多情况下,Test-NetConnection 通,但 ss 显示连接被 silently dropped,就坐实是中间设备(比如家用路由器、企业级防火墙、AWS Security Group 的 idle timeout)干的。
真正的稳定性不靠“连得上”,而靠“连得久”。Linux 上 SQL Server 的连接生命周期更裸露,也更需要你主动管控底层 TCP 行为。


















