外观
SQLServer 常见错误码
错误码概述
SQLServer 错误码由 5 位数字组成,格式为 XXXXXX,其中前两位表示错误类别。理解错误码的结构有助于快速定位和解决问题。
错误码分类
| 错误码范围 | 类别描述 |
|---|---|
| 10000-19999 | 信息性消息 |
| 20000-29999 | 用户定义的错误 |
| 30000-39999 | 语法错误 |
| 40000-49999 | 系统错误 |
| 50000-59999 | 资源相关错误 |
| 60000-69999 | 安全相关错误 |
| 70000-79999 | 服务相关错误 |
| 80000-89999 | 锁和并发相关错误 |
| 90000-99999 | 内部错误 |
常见错误码及解决方案
连接相关错误
错误 18456:登录失败
错误信息:登录失败,用户 '%.*s'。
可能原因:
- 用户名或密码错误
- 用户没有登录权限
- 数据库不可用
- 连接字符串配置错误
- 服务器身份验证模式设置问题
解决方案:
- 检查用户名和密码是否正确
- 确保用户具有登录权限
- 验证数据库是否可用
- 检查连接字符串配置
- 确认服务器身份验证模式(Windows 身份验证或 SQL Server 身份验证)
示例:
sql
-- 启用混合身份验证模式
EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE',
N'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer',
N'LoginMode', REG_DWORD, 2;错误 53:无法打开到 SQL Server 的连接
错误信息:无法打开到 SQL Server 的连接。服务器不存在或访问被拒绝。
可能原因:
- SQL Server 服务未运行
- 网络问题
- 防火墙阻止连接
- 服务器名称或端口配置错误
解决方案:
- 检查 SQL Server 服务是否正在运行
- 验证网络连接
- 检查防火墙设置,确保 SQL Server 端口(默认 1433)已开放
- 确认服务器名称和端口配置正确
- 检查 SQL Server Browser 服务是否正在运行
语法和编译错误
错误 156:关键字 'WHERE' 附近有语法错误
错误信息:关键字 '%.*s' 附近有语法错误。
可能原因:
- SQL 语句语法错误
- 关键字使用不当
- 括号不匹配
- 缺少必要的关键字
解决方案:
- 仔细检查 SQL 语句语法
- 确保所有关键字使用正确
- 验证括号是否匹配
- 检查是否缺少必要的关键字(如 SELECT、FROM 等)
示例:
sql
-- 错误示例
SELECT * products WHERE id = 1;
-- 正确示例
SELECT * FROM products WHERE id = 1;错误 207:列名 '%.*s' 无效
错误信息:列名 '%.*s' 无效。
可能原因:
- 列名拼写错误
- 列名不存在于指定的表中
- 表名或别名引用错误
- 列名包含特殊字符但未使用引号
解决方案:
- 检查列名拼写
- 验证列是否存在于指定的表中
- 确认表名或别名引用正确
- 对于包含特殊字符的列名,使用方括号 [] 或引号
权限相关错误
错误 229:拒绝了对对象 '%.*s' (数据库 '%.*s',架构 '%.*s') 的 %ls 权限
错误信息:拒绝了对对象 '%.*s' (数据库 '%.*s',架构 '%.*s') 的 %ls 权限。
可能原因:
- 用户没有执行操作所需的权限
- 权限已被撤销
- 角色成员身份问题
- 架构权限设置错误
解决方案:
- 检查用户是否具有所需权限
- 授予适当的权限
- 验证角色成员身份
- 检查架构权限设置
示例:
sql
-- 授予 SELECT 权限
GRANT SELECT ON dbo.Products TO [user_name];
-- 授予所有权限
GRANT ALL ON dbo.Products TO [user_name];锁和并发错误
错误 1205:事务(进程 ID %d)与另一个进程被死锁在 %.*ls 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
错误信息:事务(进程 ID %d)与另一个进程被死锁在 %.*ls 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
可能原因:
- 两个或多个事务相互等待对方释放资源
- 查询执行顺序不当
- 缺少适当的索引
- 事务持有锁的时间过长
解决方案:
- 重新设计事务逻辑,避免循环依赖
- 优化查询,减少锁持有时间
- 添加适当的索引,减少锁定范围
- 使用较低的隔离级别
- 实现重试机制
示例:
sql
-- 查看死锁信息
EXEC sp_who2;
EXEC sp_lock;
-- 或使用扩展事件会话监控死锁
CREATE EVENT SESSION [Deadlock_Monitor]
ON SERVER
ADD EVENT sqlserver.deadlock_graph
ADD TARGET package0.event_file(SET filename=N'deadlock_graph');资源相关错误
错误 8623:查询处理器用尽了内部资源,无法生成查询计划。这是一个罕见的事件,仅当查询过于复杂或存在系统资源不足时才会发生。
错误信息:查询处理器用尽了内部资源,无法生成查询计划。
可能原因:
- 查询过于复杂
- 缺少必要的索引
- 统计信息过时
- 服务器资源不足(内存、CPU)
解决方案:
- 简化查询,拆分为多个较小的查询
- 添加适当的索引
- 更新统计信息
- 增加服务器资源
- 优化查询设计
示例:
sql
-- 更新统计信息
UPDATE STATISTICS dbo.Products;
-- 更新所有表的统计信息
EXEC sp_updatestats;错误 9002:数据库 '%.*s' 的事务日志已满。
错误信息:数据库 '%.*s' 的事务日志已满。
可能原因:
- 事务日志未设置自动增长
- 事务日志增长设置过小
- 存在长时间运行的事务
- 事务日志未被备份
- 日志文件所在磁盘空间不足
解决方案:
- 备份事务日志(完整恢复模式下)
- 增加事务日志大小
- 调整事务日志自动增长设置
- 终止长时间运行的事务
- 确保日志文件所在磁盘有足够空间
示例:
sql
-- 备份事务日志
BACKUP LOG [DatabaseName] TO DISK = 'D:\Backup\DatabaseName_Log.bak';
-- 增加日志文件大小
ALTER DATABASE [DatabaseName]
MODIFY FILE (NAME = N'DatabaseName_Log', SIZE = 1GB, FILEGROWTH = 512MB);错误处理最佳实践
1. 使用 TRY...CATCH 块
在 T-SQL 中,使用 TRY...CATCH 块可以捕获和处理错误,提高代码的健壮性。
sql
BEGIN TRY
-- 尝试执行的代码
BEGIN TRANSACTION;
-- 执行数据库操作
INSERT INTO dbo.Products (ProductName, Price) VALUES ('New Product', 99.99);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- 处理错误
ROLLBACK TRANSACTION;
-- 获取错误信息
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
-- 记录错误
INSERT INTO dbo.ErrorLog (ErrorMessage, ErrorSeverity, ErrorState, ErrorDate)
VALUES (@ErrorMessage, @ErrorSeverity, @ErrorState, GETDATE());
-- 重新抛出错误
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;2. 记录错误信息
建立完善的错误日志系统,记录详细的错误信息,便于后续分析和调试。
3. 实现重试机制
对于临时性错误(如死锁),实现重试机制可以提高系统的可靠性。
4. 使用 RAISERROR 或 THROW 语句
在存储过程和触发器中,使用 RAISERROR 或 THROW 语句返回有意义的错误信息。
sql
-- 使用 RAISERROR(SQL Server 2012 之前)
RAISERROR ('无效的产品 ID', 16, 1);
-- 使用 THROW(SQL Server 2012 及以上)
THROW 50000, '无效的产品 ID', 1;5. 定期监控错误日志
定期查看 SQL Server 错误日志,及时发现和解决潜在问题。
sql
-- 查看错误日志
EXEC xp_readerrorlog;版本差异
SQL Server 2012 及以上版本
- 引入了
THROW语句,替代了部分RAISERROR的功能 - 增强了
TRY...CATCH块的错误处理能力 - 引入了新的错误视图:
sys.dm_exec_requests中的last_error_number列
SQL Server 2016 及以上版本
- 引入了
STRING_AGG函数,便于错误信息的聚合 - 增强了 JSON 支持,便于错误信息的结构化存储
- 引入了临时表的改进,减少了某些错误的发生
Azure SQL Database
- 提供了自动错误检测和修复功能
- 引入了新的错误类型,如连接超时和资源限制
- 提供了更详细的错误信息和诊断建议
常见问题 (FAQ)
Q: 如何查看 SQL Server 错误日志?
A: 可以通过以下方式查看错误日志:
- 在 SSMS 中,展开 "管理" > "SQL Server 日志"
- 使用
xp_readerrorlog系统存储过程 - 通过 SQL Server Configuration Manager
- 直接查看物理日志文件(默认位于
C:\Program Files\Microsoft SQL Server\MSSQLXX.MSSQLSERVER\MSSQL\Log)
Q: 如何捕获和记录存储过程中的错误?
A: 可以使用 TRY...CATCH 块捕获错误,并将错误信息插入到自定义的错误日志表中。
Q: 如何处理死锁错误?
A: 处理死锁错误的方法包括:
- 实现重试机制
- 优化查询,减少锁持有时间
- 使用较低的隔离级别
- 重新设计事务逻辑,避免循环依赖
- 添加适当的索引
Q: 如何防止事务日志已满错误?
A: 防止事务日志已满错误的方法包括:
- 定期备份事务日志
- 调整事务日志自动增长设置
- 增加初始日志文件大小
- 优化事务,减少日志生成量
- 监控日志空间使用情况
Q: 如何获取详细的错误信息?
A: 可以使用以下函数获取详细的错误信息:
ERROR_NUMBER():返回错误号ERROR_MESSAGE():返回错误消息ERROR_SEVERITY():返回错误严重性ERROR_STATE():返回错误状态码ERROR_LINE():返回发生错误的行号ERROR_PROCEDURE():返回发生错误的存储过程或触发器名称
Q: 如何区分临时性错误和永久性错误?
A: 区分临时性错误和永久性错误的方法:
- 临时性错误通常可以通过重试解决(如死锁、连接超时)
- 永久性错误需要修复根本原因(如语法错误、权限问题)
- 查看错误码和错误消息,参考官方文档判断错误类型
错误诊断工具
1. SQL Server Management Studio (SSMS)
- 错误日志查看器
- 活动监视器
- 查询执行计划分析
2. 系统存储过程
sp_who2:查看当前进程sp_lock:查看锁信息xp_readerrorlog:读取错误日志sp_errorinfo:查看错误信息
3. 动态管理视图 (DMVs)
sys.dm_exec_requests:查看当前请求sys.dm_tran_locks:查看锁信息sys.dm_os_waiting_tasks:查看等待任务sys.dm_db_missing_index_details:查看缺失索引
4. 扩展事件
- 死锁监控
- 长时间运行的查询监控
- 错误事件捕获
5. SQL Server Profiler
- 跟踪查询执行
- 监控锁和阻塞
- 分析性能问题
总结
理解和处理 SQL Server 错误是数据库开发和运维工作的重要组成部分。通过掌握常见错误码、实施有效的错误处理策略和使用适当的诊断工具,可以提高系统的可靠性和可用性。
建议定期审查错误日志,分析常见错误模式,并采取预防措施减少错误的发生。同时,建立完善的错误处理机制,确保在错误发生时能够及时捕获、记录和处理,最小化对业务的影响。
