这个错误主要涉及 tempdb 空间或系统表问题,让我们逐步检查和解决:

  1. 首先检查 tempdb 的空间使用情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 检查tempdb文件大小和可用空间
SELECT name AS [File Name],
physical_name AS [Physical Name],
size/128.0 AS [Total Size in MB],
size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT)/128.0 AS [Available Space in MB],
[file_id],
[type_desc]
FROM tempdb.sys.database_files;

-- 检查当前tempdb使用情况
SELECT session_id,
request_id,
space_used_kb/1024 as space_used_mb,
space_used_kb/1024.0/1024.0 as space_used_gb
FROM sys.dm_db_session_space_usage
WHERE space_used_kb > 0
ORDER BY space_used_kb DESC;

正常标准:

  • tempdb 应该至少有 20%的可用空间
  • 单个会话不应该占用过多 tempdb 空间
  1. 检查 tempdb 的配置
1
2
3
4
5
6
7
-- 检查tempdb文件数量和初始大小设置
SELECT [name], [physical_name],
[size]/128.0 AS [Size_MB],
[growth]/128.0 AS [Growth_MB],
[max_size],
[is_percent_growth]
FROM tempdb.sys.database_files;

建议配置:

  • tempdb 文件数量 = CPU 核心数(最多 8 个)
  • 初始大小应该足够大,避免自动增长
  • 文件大小应该相同
  • 使用固定大小增长而不是百分比
  1. 如果 tempdb 空间不足,可以进行以下操作

a. 增加 tempdb 文件大小:

1
2
3
4
5
-- 增加现有tempdb文件大小
USE master;
GO
ALTER DATABASE tempdb
MODIFY FILE (NAME = 'tempdev', SIZE = 新大小MB);

b. 添加新的 tempdb 文件:

1
2
3
4
5
6
7
8
9
10
-- 添加新的tempdb数据文件
USE master;
GO
ALTER DATABASE tempdb
ADD FILE (
NAME = 'tempdev2',
FILENAME = 'D:\SQL\tempdb2.mdf',
SIZE = 初始大小MB,
FILEGROWTH = 增长大小MB
);
  1. 检查是否有大量临时对象占用空间
1
2
3
4
5
6
7
8
-- 检查临时对象
SELECT obj.name,
obj.create_date,
OBJECT_SCHEMA_NAME(obj.object_id) as schema_name,
obj.type_desc
FROM tempdb.sys.objects obj
WHERE obj.is_ms_shipped = 0
ORDER BY obj.create_date DESC;
  1. 检查当前运行的进程
1
2
3
4
5
6
7
8
9
10
11
-- 检查可能占用大量tempdb空间的查询
SELECT r.session_id,
r.command,
r.status,
r.wait_type,
r.wait_time,
OBJECT_NAME(t.objectid) as object_name,
t.text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.session_id > 50; -- 排除系统进程
  1. 优化建议

a. tempdb 优化配置:

1
2
3
4
5
-- 设置tempdb文件的理想配置
USE master;
GO
ALTER DATABASE tempdb
MODIFY FILE (NAME = 'tempdev', SIZE = 1024MB, FILEGROWTH = 256MB);

b. 追踪 tempdb 使用情况:

1
2
3
4
5
6
7
8
-- 创建追踪标记来监控tempdb使用
CREATE EVENT SESSION [TempDB_Usage] ON SERVER
ADD EVENT sqlserver.temp_table_creation_event,
ADD EVENT sqlserver.temp_table_deletion_event
ADD TARGET package0.event_file
(SET filename=N'C:\TempDB_Usage.xel');
GO
ALTER EVENT SESSION [TempDB_Usage] ON SERVER STATE = START;
  1. 长期解决方案

  2. 定期维护计划:

    • 清理不必要的临时对象
    • 监控 tempdb 增长趋势
    • 定期重启 SQL Server 服务(在维护窗口)
  3. 预防措施:

    • 设置 tempdb 大小告警
    • 监控大型查询的 tempdb 使用情况
    • 优化使用大量 tempdb 的查询
  4. 最佳实践:

    • 将 tempdb 放在快速磁盘上
    • 避免 tempdb 文件自动增长
    • 保持文件大小一致
    • 使用多个 tempdb 文件

如果执行这些步骤后仍然遇到问题:

  1. 考虑重启 SQL Server 服务
  2. 检查是否有应用程序创建了大量临时表或表变量
  3. 评估是否需要增加服务器资源
  4. 优化可能占用大量 tempdb 空间的查询

记住:

  • 在进行任何更改之前备份重要数据
  • 在维护窗口执行可能影响性能的操作
  • 记录所有更改以便追踪问题原因