☰
SQL Server 18456错误排查:从错误日志到身份验证的完整指南
2026/10/2 14:42:21 网站建设 项目流程

在SQL Server这条路上摸爬滚打的开发者和运维,应该没人不认识18456这个数字。用户sa登录失败(18456)大概是连接类问题里曝光率最高的一条,几乎隔几天就有人拿着SSMS的报错截图来问,版本从SQL Server 2008一路问到2022,场景从本机开发到远程生产环境全都有。这个错误的烦人之处在于,它本身只告诉你“登录失败”,却不告诉你密码错了、账号禁用了、还是网络根本就没通,所以很多人一台服务器能折腾一整天。

这篇内容不会只丢给你一句“检查登录名和密码”,而是把整个排错链路拆开,从错误日志里的细节、身份验证模式的底层逻辑,到TCP/IP协议、防火墙、ODBC驱动这类中间层,一层层讲清楚。它适合刚接触SQL Server的新手照着操作,也适合有几年经验的朋友做一次系统性的查漏补缺——尤其是SQL Server 2022之后新增的强制加密行为,让很多老客户端栽了跟头,这部分我会专门拿出来讲。

1. 18456错误到底是什么:先读懂报错信息里的每一个细节

1.1 错误编号与严重级别代表什么

18456的完整名称是MSSQLSERVER_18456,严重级别为14。在SQL Server的错误体系里,Severity 14属于“用户错误”,意思是服务器本身是正常的,CPU、内存、磁盘都没问题,是你这次连接请求的身份没有被认可。这个定位很重要——它意味着收到18456时,你首要的任务不是重启SQL Server服务,而是搞清楚“是谁、用什么方式、在哪个环节被拒绝”。

顺便说一句,如果看到的是Severity 17到19的错误,那属于资源不足或数据库损坏,处理思路完全不同。所以看到18456先稳住,这通常不是一个灾难级别的故障,而是一个配置或权限问题。

1.2 报错弹窗只给你一半信息,完整原因藏在ERRORLOG里

SSMS连接失败时会弹出一个对话框,但那个对话框显示的错误信息经常是被截断的,只看得到“用户‘sa’登录失败”后面就没了。实际上SQL Server在错误日志里写下了非常精确的失败原因,这是整个排查过程中最该看的一条线索。

错误日志的默认路径一般是:

C:\Program Files\Microsoft SQL Server\MSSQL{版本编号}.{实例名}\MSSQL\Log\ERRORLOG

其中版本编号是个坑:SQL Server 2008对应MSSQL10,2008 R2对应MSSQL10_50,2012是MSSQL11,2014是MSSQL12,2016是MSSQL13,2017是MSSQL14,2019是MSSQL15,2022是MSSQL16。默认实例名为MSSQLSERVER,命名实例则是对应的实例名,比如SQLEXPRESS。

如果不想一个个去翻目录,直接在PowerShell里筛一下最快:

Get-Content "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Log\ERRORLOG" | Select-String "18456|Login failed" | Select-Object -Last 20

日志里你会看到类似这样的行:

2025-01-10 09:23:45.11 Logon Error: 18456, Severity: 14, State: 8. 2025-01-10 09:23:45.11 Logon Login failed for user 'sa'. Reason: Password did not match that for the user provided. [CLIENT: 192.168.10.25]

看到Reason:后面的内容,方向基本就定了。注意ERRORLOG文件会滚动归档,变成ERRORLOG.1、ERRORLOG.2,如果问题发生在几天前,记得去旧文件里找。

1.3 State状态码:从数字快速猜原因

每个18456错误后面都带一个State数值,虽然它不是百分百精确,但能帮你快速缩小范围。几个常见值如下:

State大致含义
1一般性登录信息错误,或者连接参数有问题
2用户ID无效,登录名不存在
5登录名有效,但验证失败,密码不对或账号被禁用
6尝试用Windows账号走SQL验证,映射不匹配
7登录已被禁用,密码也不匹配
8密码不匹配
9密码无效
11登录有效,但没有相应操作权限
12登录名被锁定或被禁用
38认证已通过,但无法打开请求的数据库

不同SQL Server版本的State含义存在细微差异,所以不要死记数字,最重要的还是看日志里的Reason:文本。比如State 38这类情况很隐蔽:用户和密码都对,但sa的默认数据库被删了、脱机了,或者sa在该数据库中没有任何权限,照样会报18456。这提醒我们,排查时别只盯着密码。

2. 为什么sa会被挡在门外:身份验证模式与账号状态的底层逻辑

2.1 身份验证模式决定了一切

SQL Server有两种身份验证模式:Windows身份验证模式和混合模式(SQL Server和Windows身份验证模式)。如果实例处于纯Windows验证模式,那么sa这种SQL登录名压根就没有参与验证的资格,你连接时客户端可能根本不会走到密码校验那一步,或者直接报18456。

很多人在安装SQL Server时为了方便选了Windows身份验证模式,安装完成后又想着用sa连,自然就撞墙了。检查当前实例是什么模式,可以执行这条SQL:

SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') AS IsWindowsOnly;

返回1表示仅Windows验证,返回0表示混合模式。想在SSMS里改的话,右键服务器节点 → 属性 → 安全性 → 服务器身份验证,选“SQL Server和Windows身份验证模式”,确定后重启SQL Server服务生效。

如果用T-SQL改,可以这样写:

USE [master]; GO EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 2; GO

这里把LoginMode设为2代表混合模式,1代表仅Windows验证。改完必须重启服务,而且重启会让所有已建立的连接断开,生产环境记得安排在业务低峰期。

2.2 sa账号的默认状态:禁用、密码策略与过期

SQL Server从2005开始大幅收紧了sa的默认策略:如果你安装时选择的是Windows身份验证模式,sa会被默认禁用;就算你选了混合模式,安装程序也会强制让你给sa设置一个强密码。换句话说,数据库从一开始就在告诉你:sa是个超级管理员,不能裸奔。

先看sa当前状态:

SELECT name, is_disabled FROM sys.sql_logins WHERE name = 'sa';

is_disabled为1表示禁用。启用并设置密码的常规写法是:

USE [master]; GO ALTER LOGIN [sa] WITH PASSWORD = N'你的新密码'; ALTER LOGIN [sa] WITH CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF; GO

CHECK_POLICY控制是否应用Windows密码复杂度策略,CHECK_EXPIRATION控制密码是否会到期。很多SQL Server 2012及之后版本的用户遇到“昨天还能用,今天突然sa登录失败”,一查日志原因写着“密码已过期”或“密码策略评估错误”,就是实例启用了密码过期策略。开发测试机上关掉这两个策略能省很多麻烦,但生产环境请务必遵守公司的安全基线,别为了省事让密码三年不换。

2.3 服务没启动、协议没启用,认证根本走不到

有时候sa账号、密码、验证模式全部正确,依然连不上,这时候要怀疑连接压根没到达认证环节。在服务器本机上打开services.msc,找到SQL Server (MSSQLSERVER)或SQL Server (你的实例名),确认状态是“正在运行”。服务没启动的情况在Express版和刚装完没重启的机器上特别常见。

另一个高频坑是TCP/IP协议被禁用。SQL Server配置管理器(SSCM)里,SQL Server网络配置 → 协议,能看到Shared Memory、Named Pipes、TCP/IP三项。如果TCP/IP显示“已禁用”,远程客户端是连不进来的,只有本机通过共享内存能连。尤其SQL Server Express安装时,TCP/IP被禁用的概率相当高。启用后别忘重启服务,TCP/IP才会真正开始监听。

3. 从客户端到服务器的三层排查链路:网络、认证与中间层

3.1 网络层先行:端口、协议、防火墙

排查连接类故障,我的习惯永远是先确认网络层通不通,再谈账号密码。在客户端机器上直接测试服务器的1433端口:

Test-NetConnection 192.168.10.20 -Port 1433

如果TcpTestSucceeded返回True,说明链路是通的,可以专心看认证问题。如果返回False,而服务器本地又能正常连接,那就要检查防火墙、端口监听和服务状态了。

在服务器上确认端口在监听:

Get-NetTCPConnection -LocalPort 1433 -State Listen

没有输出就是SQL Server没在监听这个端口。Windows防火墙需要添加入站规则放行1433/TCP;如果是命名实例(比如192.168.10.20\SQLEXPRESS),SSMS客户端会先通过1434/UDP访问SQL Server Browser服务来找到实际端口,所以远程连命名实例时,除了1433,通常还需要放行1434/UDP,或者直接写成IP地址,端口的格式绕过Browser服务。给实例配一个固定的静态端口,会让防火墙规则更干净,我推荐在SSCM的TCP/IP属性里把IPAll的TCP端口设为固定值。

3.2 用sqlcmd做最小化验证,区分网络问题还是认证问题

SSMS虽然方便,但它的连接对话框里变量太多,不适合快速定位。我排错时习惯直接用sqlcmd,一条命令就能把问题切成两半。

sqlcmd -S 127.0.0.1,1433 -U sa -P 你的密码

注意服务器名用了127.0.0.1,1433,带端口号是为了强制走TCP/IP,而不是本机的共享内存,这样测试结果更接近真实网络访问。连接成功后输入SELECT @@VERSION; GO能看到版本信息,说明认证链路完全正常。

这时候可以把测试拆成三个环境:

  • 本机测试:sqlcmd -S 127.0.0.1,1433 -U sa -P xxx,如果成功,说明SQL Server服务和凭据没问题。
  • 局域网测试:换成服务器的IP地址,如果失败,大概率是TCP/IP协议没启用、防火墙拦截或端口没监听。
  • 跨网段测试:检查路由、安全组、端口映射。

很多人会陷在“重置密码”的循环里,其实用这个办法花两分钟确认一下网络层,能省掉半天无用功。

3.3 SSMS、ODBC与Navicat连接时的差异

不同客户端对加密和协议的处理方式不一样,这也是18456在SSMS下不报、在ODBC下报,或者在Navicat下报的原因之一。

SSMS通常能自动协商加密与认证方式,但老版本SSMS连新版本SQL Server也可能出现协议不匹配。我的建议是用SSMS 19或更高版本连接SQL Server 2019/2022,遇到SSL协商类报错的概率会小很多。

ODBC连接字符串是另一个重灾区。比如用“ODBC Driver 17 for SQL Server”连接时,如果服务器端启用了强制加密,而连接字符串里写着Encrypt=Yes; TrustServerCertificate=No;,自签证书就会导致信任失败。快速解决办法是把TrustServerCertificate设为Yes(仅限测试环境),或者升级到ODBC Driver 18并正确配置证书。Navicat for SQL Server也是一样的思路,高级选项里找到TLS/SSL设置,确认证书校验和加密方式是否匹配服务器的强制加密配置。

4. 那些与18456相伴的衍生问题:2022加密、密码过期与第三方软件

4.1 SQL Server 2022强制加密引发的“证书链”错误

从SQL Server 2022开始,服务器端默认启用强制加密(Force Encryption),而它使用的又往往是自签证书。这就导致老客户端在连接时报出非常吓人的一长串错误:

[08001] [Microsoft][ODBC Driver 17 for SQL Server]SSL 提供程序: 证书链是由不受信任的颁发机构颁发的。 (-2146893019) [08001] [Microsoft][ODBC Driver 17 for SQL Server]客户端无法建立连接 (-2146893019)

别被这串错误吓到,本质是客户端不信任服务器那张自签证书。处理方式有三个方向:

  • 客户端连接字符串加TrustServerCertificate=Yes;,适合开发测试环境,跳过证书链校验。
  • 在服务器端为SQL Server配置由受信任CA签发的正式证书,比如企业内部的CA,这样客户端不需要额外信任操作。
  • 如果确定数据链路完全在内网且安全级别要求不高,可以在SSCM中把Force Encryption设为No,但这对跨公网的连接有较大安全风险,生产环境我不建议这么干。

顺带提醒,升级到ODBC Driver 18之后,它的默认加密行为变得更严格了,很多老应用连接2022实例时反而需要显式调整Encrypt参数。遇到这种问题先看驱动文档,别盲目猜测。

4.2 密码过期:SQL Server 2012及以上版本的“突然连不上”

故障场景通常是这样:某天早上开发同事跑过来,说“数据库连不上了,报sa登录失败”,然后你查日志,发现18456对应的State是5,Reason写着密码过期或密码策略评估错误。这类问题在SQL Server 2012及以上版本中很常见,因为SQL登录名默认会继承操作系统密码策略,如果服务器策略要求密码定期过期,sa到了期限就会失去效力。

处理分两步。第一步,用Windows身份验证方式通过SSMS或sqlcmd登录实例,把sa密码重置掉;第二步,判断这台机器是否需要密码过期策略。开发测试机直接关掉:

ALTER LOGIN sa WITH CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF;

但如果这是合规要求较高的生产环境,我建议保留策略,同时在团队日历或运维平台里登记密码轮换计划,而不是临时抱佛脚。很多公司都是等到sa到期的那天才想起来改密码,这个习惯不值得学。

4.3 第三方软件连不上:SolidWorks Electrical这类软件的排查方法

“SolidWorks Electrical无法连接到SQL Server”这类问题,本质跟手动用SSMS连接没有任何区别,只是报错文案更吓人一些。这类软件通常会随安装包部署一个SQL Server实例,比如某个命名实例,然后在配置文件中写入服务器名和数据库名。连接失败时,最有效的办法是先用SSMS手动去连那个目标实例:计算机名\实例名或IP地址\实例名。

如果SSMS能连上,说明SQL Server层没问题,问题出在软件自身的配置上,比如服务器名写错、端口写错、软件服务账户没有权限。如果SSMS也连不上,那就回到本文前面说的排查链路:SQL Server服务是否在运行、TCP/IP是否启用、防火墙是否放行、sa或其他连接账号是否可用。把这套链路走完,绝大多数第三方软件的“无法连接SQL Server”问题都能定位。

4.4 容易混淆的几种“登录失败”

有些报错虽然长得像,但根本不是SQL Server层面的问题,排查方向完全不同。比如Windows系统的“登录失败: 未授权用户在此计算机上的请求登录类型”,这通常是Windows账户权限、远程桌面或共享访问的问题,跟SQL Server的18456没有直接关系。还有一种云环境常见的“login server error: token exchange failed: token endpoint returned...”,那是OAuth/Entra认证流程的问题,常见于Azure SQL或托管实例,处理时要去看云平台的接入配置,而不是翻SQL Server错误日志。

遇到任何“登录失败”报错,先确认报错来自SQL Server的登录层,还是来自操作系统或云服务的认证层。这个判断能帮你省下大量无效操作。

5. 十分钟自查清单:按顺序执行这几条

5.1 快速定位18456的对照表

下面这张表是我排错时实际使用的清单,从最常出问题的项开始排,一次扫完基本能定位九成问题。

排查项快速验证方法失败时的对策
SQL Server服务状态Get-Service MSSQLSERVER或services.msc启动服务,并设为自动启动
TCP/IP协议是否启用SQL Server配置管理器 → 协议启用TCP/IP,重启服务
端口是否监听Get-NetTCPConnection -LocalPort 1433检查实例静态端口,确认没有端口冲突
防火墙是否放行客户端执行Test-NetConnection IP -Port 1433添加入站规则放行1433/TCP(命名实例加1434/UDP)
身份验证模式SELECT SERVERPROPERTY('IsIntegratedSecurityOnly');改为混合模式,重启服务
sa账号是否禁用SELECT name, is_disabled FROM sys.sql_logins WHERE name='sa';ALTER LOGIN sa ENABLE;
密码是否正确sqlcmd -S 127.0.0.1,1433 -U sa -P 密码重置sa密码
密码策略与过期查看日志中Reason是否提到password过期ALTER LOGIN sa WITH CHECK_POLICY=OFF, CHECK_EXPIRATION=OFF;
默认数据库是否可用SELECT name FROM sys.databases;检查sa的默认库ALTER LOGIN sa WITH DEFAULT_DATABASE=master;

最后一行是很多人漏掉的:sa的默认数据库如果被改成某个已删除或脱机的库,即使密码完全正确,登录时也会报18456,State通常是38。修复方式很简单,把默认数据库改回master即可。

5.2 让我少走弯路的几个习惯

第一,永远先看ERRORLOG再动配置。日志里的Reason字段直接指明了方向,靠猜不如靠看。第二,改身份验证模式、启用TCP/IP这类操作都要重启SQL Server服务,重启意味着所有连接断开,生产环境务必先申请维护窗口。第三,sa密码变更记录要留痕,团队里最怕“某个人知道密码,但他休假了”。第四,不要图方便把所有环境都改成混合模式,Windows身份验证在域环境下更安全,SQL登录名只给确有需要的场景使用。

最后多说一句

排查18456这么多年,我的体会是:这问题百分之八十不是密码错了,而是服务没起来、TCP/IP没启用、防火墙没放行、sa被禁用这四件事。把顺序理顺,先确认链路再谈凭据,十分钟内基本能收工。如果你经常需要在远程机器上排查,建议把下面这条命令存成一个小脚本,每次连不上先跑一遍,把日志里最近20条18456发给我,比发一张SSMS报错截图有用得多。

Get-Content "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Log\ERRORLOG" | Select-String "18456" | Select-Object -Last 20

希望这篇清单能帮你在下次遇到sa登录失败时,把排查时间从半天压缩到十分钟。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询