Laravel(Ubuntu/Forge部署)连接SQL Server登录超时问题
在Ubuntu服务器上通过Forge部署的Laravel应用,尝试连接SQL Server时出现登录超时错误,但服务器命令行可正常连接该数据库。
命令行连接成功记录
forge@server:/etc/php/8.1/fpm$ sqlcmd -S HOST\\INSTANCENAME -U USER -P PASSWORD -C
Laravel相关配置
database.php 中的连接配置
'bp_database' => [ 'driver' => 'sqlsrv', 'host' => env('BP_DB_HOST'), 'port' => env('BP_DB_PORT'), 'database' => env('BP_DB_DATABASE'), 'username' => env('BP_DB_USERNAME'), 'password' => env('BP_DB_PASSWORD'), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'charset' => 'utf8', 'prefix' => '', 'prefix_indexes' => true, 'trust_server_certificate' => true, ],
.env 配置项
BP_DB_CONNECTION=bp_database BP_DB_HOST=HOST BP_DB_PORT=1433 BP_DB_DATABASE=INSTANCENAME BP_DB_USERNAME=USER BP_DB_PASSWORD=PASSWORD
测试控制器代码(TestController.php)
public function testBPDatabase() { try { DB::connection('bp_database')->getPdo(); dd('连接成功'); } catch (\Exception $e) { dd("数据库连接失败,请检查配置。错误信息:" . $e ); } }
问题总结
- 默认MySQL连接测试完全正常
- 测试
bp_database连接时持续失败 - 服务器命令行可正常连接目标SQL Server数据库
- 已反复确认.env配置信息无误
错误提示
PDOException: SQLSTATE[HYT00]: [Microsoft][ODBC Driver 18 for SQL Server]登录超时已过期 in /home/forge/default/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
原生PHP测试结果
为排除Laravel框架影响,使用微软官方文档提供的原生PHP连接代码测试,仍出现相同错误:
原生连接代码
$serverName = "172.36.100.2\\BPSINSTANCE"; $connectionInfo = array( "UID"=>"bpsrawdata", "PWD"=>"password"); $conn = sqlsrv_connect( $serverName, $connectionInfo); if( $conn ) { echo "连接成功<br />"; }else{ var_dump( sqlsrv_errors()); die(); }
错误信息
[Microsoft][ODBC Driver 17 for SQL Server]登录超时已过期
错误堆栈详情
无法定位指定的服务器/实例
解决方案建议
1. 修正SQL Server实例的连接格式
命令行中用HOST\\INSTANCENAME指定实例,但Laravel配置错误地将实例名放到了database字段。SQL Server的实例名需与主机地址合并到host字段,格式为HOST\INSTANCENAME;同时注意:database字段要填实际要连接的数据库名称,而非实例名。
调整.env配置示例:
BP_DB_HOST=HOST\INSTANCENAME BP_DB_PORT=1433 # 命名实例若使用动态端口,需替换为实际端口 BP_DB_DATABASE=你的目标数据库名称
2. 统一ODBC驱动版本
命令行sqlcmd与PHP使用的ODBC驱动版本差异可能导致兼容性问题,可通过以下命令查看sqlcmd使用的驱动版本:
sqlcmd -? | grep Driver
若版本差异较大,建议升级或降级PHP的ODBC驱动至匹配版本。
3. 确认实例端口并调整连接格式
命名实例默认使用动态端口,PHP驱动可能无法自动解析。可通过SQL Server配置管理器或执行以下SQL查询获取实例端口:
SELECT local_tcp_port FROM sys.dm_exec_connections WHERE session_id = @@SPID;
拿到端口后,可改用主机地址,端口号的格式指定连接(无需实例名):
BP_DB_HOST=HOST,1434 # 替换为查询到的实际端口 BP_DB_PORT=
4. 检查并配置PHP sqlsrv扩展
确保PHP已正确安装并启用sqlsrv与pdo_sqlsrv扩展,可通过phpinfo()查看模块状态。若未安装,针对Ubuntu PHP8.1执行以下命令:
sudo pecl install sqlsrv pdo_sqlsrv sudo echo "extension=pdo_sqlsrv.so" >> /etc/php/8.1/fpm/php.ini sudo echo "extension=sqlsrv.so" >> /etc/php/8.1/fpm/php.ini sudo systemctl restart php8.1-fpm
5. 开放防火墙端口
确认Ubuntu服务器防火墙(ufw)已开放SQL Server实例的端口:
sudo ufw allow 1433/tcp sudo ufw allow 1434/tcp # 命名实例需开放浏览器服务端口 sudo ufw reload
同时确保SQL Server所在服务器的防火墙允许Ubuntu服务器IP访问。
6. 延长连接超时时间
在Laravel数据库配置中添加超时参数,延长连接等待时间:
'bp_database' => [ // 其他配置... 'timeout' => 30, // 单位:秒 ],
内容的提问来源于stack exchange,提问作者KayleeGrace

