本文共 2540 字,大约阅读时间需要 8 分钟。
昨天被一个数据库的问题折腾了半天,把解决过程记录下来。
[项目背景]
基于MSSQL的一个项目,考虑到用户环境可能没有数据库系统,因此自带了MSDE 2000 SP4,允许用户选装。整个项目由多个服务构成,允许分布式安装,因此安装MSDE时开启了远程访问。
PS:我知道分布式系统还允许用户用MSDE确实挺BT的,不过项目就这么要求的,没办法。
[问题]
在一台Windows Server 2008上部署系统,选择安装MSDE,结果数据库实例无法连接,导致安装失败。
先用osql.exe尝试连接了一下:
连接失败,无论本机还是远程都不行,排除了防火墙问题。
用svrnetcn命令检查协议,有TCP/IP协议,端口号是随机的45592,然后再用osql.exe指定端口号连接了一下:
这回成功了,而且本机和远程都能连上。
[分析与解决]
对应用程序来说,要访问远程服务器上的MSDE,它是如何知道该连接哪个端口呢?在启用了TCP/IP协议的情况下,sqlservr.exe(MSSQL服务程序)除了开启指定的tcp端口(比如本例中的45592),还会开启一个固定的udp 1434。这样应用程序先通过udp询问,得到指定实例对应的tcp端口号,再发起连接。
执行“netstat -ano | findstr 1434”看了一下,果然没有udp1434,但tcp 45592是处于监听状态的。
为了对比,特意找了另一台正常的机器看了一下,有udp 1434的监听,进程就是msde的服务进程sqlservr.exe。
看来是有程序干扰了MSDE的服务监听udp 1434,但又肯定不是端口冲突,没有进程在使用这个端口。进系统服务看了一下,结果发现这台机器上还随着Visual Studio 2005安装了SQL Express 2005(实例名sqlexpress),但几个服务都没有处于启动状态。
对MSSQL 2005系列来说,udp 1434不再由sqlservr提供了,而是改到了一个叫SQL Server Browser的服务上,看来MSDE在启动的时候,受2005的影响(虽说sqlbrowser服务并没有启动),不知出于什么原因,没有开启udp1434或是开启失败了,导致命名实例无法解析。
net start一下这个sqlbrowser服务,猜测它会接管对两个命名实例的解析,满心欢喜的以为问题能解决,结果对2005的实例能解析,msde的实例依然不行,晕倒。
开始上网查阅资料,无果。
为什么sqlbrowser服务不解析msde的实例呢?尝试用调试方式启动了sqlbrowser,想碰碰运气,这个文件在 C:\Program Files\Microsoft SQL Server\90\Shared 目录下:
然后再用osql连接,居然成功了,远程也可以了。
为何服务方式不行而命令行可以?两者最大的区别应该是运行帐号的问题,去服务里查了一下,SQL Server Browser服务是用Network Service帐户启动的,而产品中安装MSDE时用的是admin权限,猜测sqlbrowser以服务方式启动时,尝试去读MSDE的某些配置失败,因此无法为其提供解析服务。
把sqlbrowser服务切换到local system下,再试,一切正常了。为了防止有缓存的问题,特意重启了机器,证明确实是OK了。
[解决方案]
原因是找到了,不过只能说是找到了MSDE和SQL Express并存的方法,对于产品来说,问题还未解决,想了想,有以下几种解决方案:
方案一:
完全卸载SQL Express 2005,保证机器上只有MSDE,没有冲突就没有问题。不过对于一个产品来说,对用户的环境要求就更高了一些。
方案二:
开启SQL Server Browser服务,并且确保合适的帐户权限。这个说实话,让用户来处理有点不合适,由安装程序来做,复杂度会增加不少。
方案三:
安装MSDE时指定端口号,应用程序连接时一律用明确的端口号连接,比如C#,连接串写成:
这样似乎修改代价最小。至于如何修改MSDE端口号,这个在安装时是没法指定的,可以由安装程序修改注册表,再重启服务。
注册表键值位于 HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/实例名/MSSQLServer/SuperSocketNetLib/Tcp,修改其下的TcpDynamicPorts和TcpPort为需要的值,注意不要和已有端口冲突,否则服务起不来。
[补充]
微软官方的这篇文章挺不错,
转载地址:http://tkpml.baihongyu.com/