深入探讨SQL Server中DAC连接及其它
DAC(Dedicated Admin Connection)是SQL Server 2005引入的一个东西,目的是在SQL Server发生严重性能问题的时候仍保留有限的资源保证管理员能够执行一些简单的命令用于问题诊断、释放资源、杀死肇事进程等。微软官方对DAC的说明:使用专用管理员连接。对于DAC使用的一般情况,有两个不错的Blog值得推荐:
http://www.cnblogs.com/kerrycode/p/3344085.html
http://www.cnblogs.com/lyhabc/archive/2012/09/23/2698702.html
上面的两篇blog涉及到的基本是DAC访问单机单实例的情况。本文试图对DAC访问单机多实例的情况也做个探讨。
1)单机单SQL Server实例,且SQL Server实例使用默认端口(1433)
--以下的形式都可以访问 sqlcmd -S myServer -U myUser -P myPassword -A sqlcmd -S ADMIN:myServer -U myUser -P myPassword sqlcmd -S myServer,1434 -U myUser -P myPassword sqlcmd -S xxx.xxx.xxx.xxx -U myUser -P myPassword -A sqlcmd -S xxx.xxx.xxx.xxx,1434 -U myUser -P myPassword
说明: a) sqlcmd命令行中参数与参数值之间可以有空格也可以没有;如果你的密码中有空格,你可以用双引号把你的密码引起来; b) sqlcmd命令中的“-S”其实也可以用"/S",其它参数也一样; c) 1434是SQL Server连接的默认端口号; d) 在服务器前加"ADMIN:"也是为了指定进行DAC连接; e) “-A”是在sqlcmd命令行中指定DAC连接的参数; f) "-A","ADMIN:",",1434"不能在一条命令中出现两个或以上,否则会报错; g) 不在命令行中加入这3个参数("-A","ADMIN:",",1434")的任何一个,登录也能成功,差别在于你使用的连接是普通连接,不是DAC连接。一般来说,普通连接能用的资源更多,但是当系统性能出现严重问题的时候普通连接可能没法建立,这也是引入DAC的初衷;再就是DAC连接下能看到一些有助于诊断的秘密视图(参见上面推荐的第一个blog)。
2)单机单SQL Server实例,SQL Server实例使用非默认端口
我通过测试得到的结论是:对于单机单SQL Server实例,使用非默认端口时候的DAC访问跟使用默认端口1433时候完全一样。网上的一些论坛说要确保“SQL Server Browser”在运行,似乎不是必要的,至少我测试(用的SQL Server 2008 R2 SP3)过程中“SQL Server Browser”是不是在运行不影响访问。
3)单机多SQL Server实例
通过DAC来访问单机多SQL Server实例的情况要复杂一些。上面的几条命令行在这种情况下都会失效。原因在两个: a) DAC访问是实例级别的,服务端得有办法知道你要访问的是哪个实例; b) 在单机多实例的情况下监视DAC访问的是随机端口,而不再是默认的1434(当然,具体的端口号在SQL Server启动的时候是确定的,可以在SQL Server启动的Log中找到:打开SSMS--->连接到数据库实例--->Management--->SQL Server Logs--->Current,在里面找到类似”Dedicated admin connection support was established for listening locally on port 50458.“) --怎么破? 我们在访问数据库引擎的时候,碰到单机多实例的情况有两种办法,一种是在配置S参数的时候加上实例名,一种是加实例端口号。命令行的形式类似下面: sqlcmd -S myServer\InstanceName -U myUser -P myPassword sqlcmd -S xxx.xxx.xxx.xxx\InstanceName -U myUser -P myPassword sqlcmd -S myServer,6xxx -U myUser -P myPassword sqlcmd -S xxx.xxx.xxx.xxx,6xxx -U myUser -P myPassword 先从实例名着手: sqlcmd -S myServer\InstanceName -U myUser -P myPassword -A sqlcmd -S xxx.xxx.xxx.xxx\InstanceName -U myUser -P myPassword -A sqlcmd -S ADMIN:myServer\InstanceName -U myUser -P myPassword sqlcmd -S ADMIN:xxx.xxx.xxx.xxx\InstanceName -U myUser -P myPassword 经测试确认,以上4种连接方式都是OK的。注意一点,对于InstanceName的解析是服务器上的“SQL Server Browser”进行的,如果这个服务不在运行,DAC的访问是要失败的。流程是:Browser根据“myServer\InstanceName”或者“xxx.xxx.xxx.xxx\InstanceName”找到你要访问的实例,然后根据“-A”或者“ADMIN:”找到你要访问的端口。 既然这样可以进行DAC访问,那用类似访问数据库引擎的方式,把上面命令中的“\InstanceName”改成",xxxx"格式的端口号是不是也行呢? sqlcmd -S myServer,xxxx -U myUser -P myPassword -A sqlcmd -S xxx.xxx.xxx.xxx,xxxx -U myUser -P myPassword -A sqlcmd -S ADMIN:myServer,xxxx -U myUser -P myPassword sqlcmd -S ADMIN:xxx.xxx.xxx.xxx,xxxx -U myUser -P myPassword 如果你在几个命令行中配的端口号跟访问数据库引擎时候配置的端口号是一样的话,答案是不行。原因在哪里呢?那个端口是数据库引擎的访问端口,并不是被监听的DAC端口,因为不在一个频道上DAC还不知道你想访问。我的理解,在命令行中指定了端口号的情况下,Browser认为那就是你想访问的端口,结果因为它并不是那个随机的DAC端口而导致了失败。 DAC访问侦听跟数据库引擎一样,从根本上来说也是一个tcp服务(关于这一点你可以查看sys.endpoints来确认)。是服务,我们如果能知道它侦听的端口号就应该能解决问题。但不幸也在这儿,如上面b)所说,在单机多实例的情况下这个被监听的端口是随机的。视图sys.endpoints是能查到当前SQL Server实例上的tcp服务信息的,每个endpoint都有一条记录,比如你就能在这里查到用于镜像的5022,但遗憾的是对于DAC,端口那一列却显示的是0.通过端口访问的这条路我没能走通。
4)DAC访问与防火墙
如果有人通过我上面提到的有效的方式进行DAC访问却不幸失败了,也请不要奇怪。抛开端口劫持等特殊情况,DAC访问失败最常见的就是受到防火墙设置的拦截。对于上面提到的两种单机单实例的情况,只要确认服务端配置了允许对tcp1434端口的访问,DAC连接应该是没有问题的;复杂的情况仍然是单机多实例。 对于单机多实例的情况,由于DAC侦听的端口是随机的,不能指定,所以我们没法在防火墙上给它开口子,除非关闭防火墙。事实上,我在测试的时候就是让服务器上的Windows防火墙对域范围内的访问不起作用(关闭针对域内部访问的拦截)的。那要想从外网访问怎么办?总不能为了一个DAC连接把这台服务器赤裸裸的暴露出来(给它配外网IP)或者关掉公司的级别的防火墙吧?这倒不必,可以用VPN或者端口映射从防火墙上开个小口子,这样你就能连接到局域网,从那进行DAC访问。
5)如何确认当前是DAC连接还是普通连接
可以使用下面的SQL: select s.session_id, s.login_time, s.login_name, s.host_name, p.endpoint_id, p.protocol_desc, p.name from sys.dm_exec_sessions s inner join sys.endpoints p on s.endpoint_id = p.endpoint_id 你可以从login_time,login_name,host_name来判断出哪一个是你当前的连接session,如果是DAC连接的话,你能从name列看到“Dedicated Admin Connection”。