SQL Server 常用运维指令手册
SQL Server 常用运维指令手册
适用版本:SQL Server 2017 / 2019 / 2022 / 2025(Windows 与 Linux 均适用) 约定:
#root 或 sudo,>Windows 命令行,sqlcmd>sqlcmd 提示符,<xxx>为占位符。 差异标注:正文用> **版本差异**引用块标注跨版本不一致之处。 更新时间:2026-11
目录
- 版本与支持周期
- 下载地址与安装
- 服务管理与启动参数
- sqlcmd 与客户端连接
- 实例配置与 sp_configure
- 登录名、用户与权限
- 数据库与文件管理
- 恢复模式与日志管理
- 备份与恢复
- 高可用:Always On 与日志传送
- 日志体系与错误排查
- 性能诊断:DMV 与 Query Store
- 锁、阻塞与死锁
- 空间与容量管理
- tempdb 与内存管理
- 升级、迁移与补丁
- 高频故障速查
- 危险命令与避坑清单
- 附录:巡检脚本与 DMV 速查
1. 版本与支持周期
1.1 版本对照
| 版本 | 内部版本 | GA 时间 | 主流支持至 | 扩展支持至 | 状态 |
|---|---|---|---|---|---|
| 2016 | 13.x | 2016-06 | 2021-07 | 2026-07-14 | 已过扩展支持 |
| 2017 | 14.x | 2017-10 | 2022-10 | 2027-10-12 | 扩展支持中 |
| 2019 | 15.x | 2019-11 | 2025-02 | 2030-01-08 | 扩展支持中 |
| 2022 | 16.x | 2022-11 | 2027-01 | 2033-01-11 | 广泛使用 |
| 2025 | 17.x | 2025-11-18 | 2030-01 | 2035-01 | 当前推荐 |
注意:SQL Server 采用"主流支持 5 年 + 扩展支持 5 年"模型。扩展支持期只有安全更新,没有功能修复。2016 已于 2026-07 完全退出支持,仍在使用需尽快升级。
1.2 版本识别
SELECT @@VERSION;
-- Microsoft SQL Server 2025 (RTM-CU10) - 17.0.5035.5 (X64) ...
SELECT SERVERPROPERTY('ProductVersion') AS product_version, -- 17.0.5035.5
SERVERPROPERTY('ProductLevel') AS patch_level, -- RTM / SP1 / CU10
SERVERPROPERTY('Edition') AS edition, -- Enterprise / Standard / Express
SERVERPROPERTY('ProductUpdateLevel') AS cu, -- CU10
SERVERPROPERTY('Collation') AS collation,
SERVERPROPERTY('IsIntegratedSecurityOnly') AS windows_auth_only;
# Linux
/opt/mssql/bin/mssql-conf traceflag 1234 off
cat /var/opt/mssql/mssql.conf
1.3 版本与功能限制
| 版本 | 关键限制 |
|---|---|
| Express | 单库 10 GB、1 CPU/4 核、1.4 GB 缓冲池 |
| Standard | 24 核、128 GB 缓冲池、基础 Always On(2 副本) |
| Enterprise | 无限制,完整 Always On、在线索引、分区并行 |
避坑:Standard 版做 Always On 只能 2 个副本且无只读路由,规划高可用前先确认版本,否则方案到实施才发现不可行。
2. 下载地址与安装
2.1 官方入口总表
| 用途 | 地址 |
|---|---|
| 下载总入口 | https://www.microsoft.com/sql-server/sql-server-downloads |
| 2025 免费版(Developer / Express) | 同上,页面内选择 |
| Express 独立下载 | https://www.microsoft.com/download/details.aspx?id=108836 |
| Linux 安装文档 | https://learn.microsoft.com/sql/linux/sql-server-linux-setup |
| Linux 软件源(Microsoft) | https://packages.microsoft.com/ |
| Docker 镜像 | mcr.microsoft.com/mssql/server:2025-latest |
| 补丁与 CU 列表 | https://support.microsoft.com/help/321185 |
| 官方文档 | https://learn.microsoft.com/sql/ |
| SQL Server Management Studio(SSMS) | https://learn.microsoft.com/sql/ssms/download-sql-server-management-studio-ssms |
| Azure Data Studio | https://learn.microsoft.com/sql/azure-data-studio/ |
| 评估与功能对比 | https://www.microsoft.com/sql-server/sql-server-2025-features |
许可说明:Developer 版功能等同 Enterprise,仅限开发测试;生产必须购买 Standard/Enterprise 授权,或使用 Express(免费但有容量限制)。
2.2 Windows 安装
图形安装要点:
- 选择 Developer 或 Express 版本。
- 实例选择:默认实例(
MSSQLSERVER,端口 1433)或命名实例(MSSQL$INST01,动态端口)。 - 服务账户:建议用域账户或虚拟账户
NT Service\MSSQLSERVER,不要用 LocalSystem。 - 排序规则:
Chinese_PRC_CI_AS或Latin1_General_100_CI_AS_SC_UTF8(UTF-8 需 2019+)。 - 认证模式:混合模式(SQL 登录 + Windows 认证),并设置
sa密码。 - 数据目录:把 data/log/backup 分盘存放。
静默安装(命令行):
setup.exe /Q /ACTION=Install /FEATURES=SQLENGINE /INSTANCENAME=MSSQLSERVER ^
/SECURITYMODE=SQL /SAPWD="Str0ng#Pass2026" ^
/SQLSVCACCOUNT="NT Service\MSSQLSERVER" /SQLSYSADMINACCOUNTS="BUILTIN\Administrators" ^
/AGTSVCACCOUNT="NT Service\SQLSERVERAGENT" ^
/SQLCOLLATION="Chinese_PRC_CI_AS" ^
/SQLDATADIR="D:\MSSQL\Data" /SQLUSERDBLOGDIR="E:\MSSQL\Log" /SQLBACKUPDIR="F:\MSSQL\Backup" ^
/TCPENABLED=1 /NPENABLED=0 /IACCEPTSQLSERVERLICENSETERMS
2.3 Linux 安装(RHEL / Ubuntu)
# RHEL 8/9
curl -o /etc/yum.repos.d/mssql-server.repo https://packages.microsoft.com/config/rhel/9/mssql-server-2025.repo
dnf install -y mssql-server
/opt/mssql/bin/mssql-conf setup
systemctl enable --now mssql-server
# Ubuntu 22.04/24.04
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
curl -o /etc/apt/sources.list.d/mssql-server.list \
https://packages.microsoft.com/config/ubuntu/24.04/mssql-server-2025.list
apt update && apt install -y mssql-server
/opt/mssql/bin/mssql-conf setup
systemctl enable --now mssql-server
mssql-conf setup 交互项:版本(Developer/Express/Standard/Enterprise)、语言、sa 密码(需满足复杂度:8 位以上,含大小写、数字、符号)。
# 非交互
MSSQL_PID=Developer ACCEPT_EULA=Y MSSQL_SA_PASSWORD='Str0ng#Pass2026' \
/opt/mssql/bin/mssql-conf -n setup
# 安装命令行工具
curl -o /etc/yum.repos.d/msprod.repo https://packages.microsoft.com/config/rhel/9/prod.repo
dnf install -y mssql-tools18 unixODBC-devel
echo 'export PATH=$PATH:/opt/mssql-tools18/bin' >> /etc/profile.d/mssql.sh
2.4 Docker 部署
docker run -d --name mssql2025 \
--restart unless-stopped \
-e ACCEPT_EULA=Y \
-e MSSQL_SA_PASSWORD='Str0ng#Pass2026' \
-e MSSQL_PID=Developer \
-p 1433:1433 \
-v /data/mssql:/var/opt/mssql \
mcr.microsoft.com/mssql/server:2025-latest
docker logs -f mssql2025
docker exec -it mssql2025 /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Str0ng#Pass2026' -C
注意:
MSSQL_SA_PASSWORD不满足复杂度要求容器会直接退出,日志里提示密码策略。至少 8 位且包含三类字符。
2.5 安装后必做
-- 1) 确认版本与实例
SELECT @@SERVERNAME, @@VERSION;
SELECT SERVERPROPERTY('InstanceName'), SERVERPROPERTY('IsClustered');
-- 2) 确认认证模式(1 = 仅 Windows,0 = 混合)
SELECT SERVERPROPERTY('IsIntegratedSecurityOnly');
-- 3) 限制最大内存(生产必须,否则会吃光系统内存)
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'max server memory (MB)', 28672; RECONFIGURE;
-- 4) 开启远程连接与 TCP 端口(Linux 默认已开)
EXEC xp_readerrorlog 0, 1, N'Server is listening on';
-- 5) 改 sa 密码
ALTER LOGIN sa WITH PASSWORD = 'NewStr0ng#2026';
# 防火墙放行
firewall-cmd --add-port=1433/tcp --permanent && firewall-cmd --reload
3. 服务管理与启动参数
3.1 服务清单
| 服务 | 作用 |
|---|---|
MSSQLSERVER / MSSQL$INST01 |
数据库引擎 |
SQLSERVERAGENT / SQLAgent$INST01 |
代理,跑作业与备份计划 |
SQLBrowser |
命名实例的端口解析(UDP 1434) |
SQLWriter |
VSS 备份支持 |
MsDtsServer |
SSIS |
3.2 Windows
Get-Service MSSQLSERVER
Start-Service MSSQLSERVER
Stop-Service MSSQLSERVER
Restart-Service MSSQLSERVER
Set-Service MSSQLSERVER -StartupType Automatic
net start MSSQLSERVER
net stop MSSQLSERVER
sc query MSSQLSERVER
# 命名实例
Get-Service 'MSSQL$INST01'
net start 'MSSQL$INST01'
3.3 Linux
systemctl start mssql-server
systemctl stop mssql-server
systemctl restart mssql-server
systemctl status mssql-server
systemctl enable mssql-server
journalctl -u mssql-server -n 200 --no-pager
3.4 启动参数(跟踪标志)
# Linux:在 mssql.conf 中配置
cat /var/opt/mssql/mssql.conf
[sqlagent]
enabled = true
[memory]
memorylimitmb = 28672
[traceflag]
traceflag0 = 3226
traceflag1 = 1117
traceflag2 = 1118
# Windows:SQL Server 配置管理器 → 启动参数,或用注册表
# 常用跟踪标志:
# 3226 备份成功不写 errorlog(减少日志噪音)
# 1117 数据文件统一增长
# 1118 统一区分配(2016 起默认由混合区分配替代,通常不需要)
# 1222 死锁信息写入 errorlog
# 1204 记录死锁资源与锁(老版本)
# 4199 查询优化器修复全部开启(2016 起默认行为随兼容级别)
建议:生产至少开
3226(备份日志噪音)与1222(死锁可追溯)。其他标志按实际问题加,不要盲抄网上的"性能优化跟踪标志"清单。
3.5 重启前的检查
-- 有没有正在跑的作业/长事务
SELECT session_id, status, command, wait_type, blocking_session_id, cpu_time, total_elapsed_time
FROM sys.dm_exec_requests WHERE session_id > 50;
-- 有没有未提交事务
SELECT * FROM sys.dm_tran_active_transactions;
-- 检查点,减少重启恢复时间
CHECKPOINT;
4. sqlcmd 与客户端连接
4.1 基本连接
sqlcmd -S localhost -U sa -P 'Str0ng#Pass2026' -C
sqlcmd -S 10.0.0.11,1433 -U app -P 'App#2026' -d appdb -C
sqlcmd -S "tcp:10.0.0.11,1433" -U app -P 'App#2026' -d appdb -N -C
sqlcmd -S localhost -E # Windows 集成认证
sqlcmd -S localhost -U sa -P 'xxx' -Q "SELECT @@VERSION"
sqlcmd -S localhost -U sa -P 'xxx' -i script.sql -o out.txt
关键参数:
| 参数 | 作用 |
|---|---|
-S server[,port] |
服务器与端口 |
-d dbname |
初始数据库 |
-U / -P |
SQL 登录 |
-E |
Windows 集成认证 |
-C |
信任服务器证书(自签证书必加) |
-N |
加密连接 |
-Q |
执行一条语句后退出 |
-i / -o |
输入脚本 / 输出文件 |
-h -1 |
不输出表头 |
-W |
去掉列尾空格 |
-s "," |
列分隔符 |
-b |
出错返回非 0 退出码(脚本必须加) |
# 脚本化标准写法
sqlcmd -S localhost -U sa -P "$SA_PWD" -d master -b -r1 -W -s "," -Q "SET NOCOUNT ON; SELECT name FROM sys.databases"
4.2 常用命令(sqlcmd 内)
sqlcmd> :help
sqlcmd> :list
sqlcmd> :r /tmp/other.sql -- 引入脚本
sqlcmd> :setvar dbname appdb
sqlcmd> :exit
sqlcmd> GO -- 批处理结束符(不是分号)
关键:T-SQL 用
GO分隔批,不是分号。CREATE VIEW、CREATE PROCEDURE必须是批内第一条语句,前面要有GO。
4.3 连接排障
# 1) 端口通不通
ss -lntp | grep 1433
telnet 10.0.0.11 1433
nc -zv 10.0.0.11 1433
# 2) 实例在不在
sqlcmd -S localhost -U sa -P 'xxx' -Q "SELECT 1"
# 3) 命名实例的端口(需 SQL Browser)
sqlcmd -S 10.0.0.11\INST01 -U sa -P 'xxx'
# 4) 强制 TCP 并指定端口
sqlcmd -S "tcp:10.0.0.11,1433" -U sa -P 'xxx'
常见错误:
| 错误号 | 含义 |
|---|---|
| 18456 | 登录失败(密码错 / 账号禁用 / 仅 Windows 认证) |
| 4060 | 无法打开数据库(库不存在 / 无权限 / 离线) |
| 233 | 连接被对端关闭(TLS/协议不匹配) |
| 258 | 连接超时(网络/防火墙) |
| 1225 | 远程连接被拒(未启用 TCP/IP) |
| 53 | 找不到服务器(名称解析/实例名错) |
5. 实例配置与 sp_configure
5.1 查看配置
EXEC sp_configure; -- 只显示常用项
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure; -- 显示全部
SELECT name, value, value_in_use, minimum, maximum, is_dynamic, is_advanced
FROM sys.configurations ORDER BY name;
value 是配置值,value_in_use 是当前生效值。is_dynamic=1 的改完 RECONFIGURE 立即生效,0 的需要重启服务。
5.2 修改配置
EXEC sp_configure 'max server memory (MB)', 28672;
RECONFIGURE; -- 动态项立即生效
EXEC sp_configure 'max degree of parallelism', 8;
RECONFIGURE;
EXEC sp_configure 'cost threshold for parallelism', 50;
RECONFIGURE;
EXEC sp_configure 'optimize for ad hoc workloads', 1;
RECONFIGURE;
注意:
RECONFIGURE只对动态项生效,静态项(如min server memory)需要RECONFIGURE WITH OVERRIDE+ 重启服务。改完必须验证value_in_use。
5.3 生产必调参数
| 参数 | 建议 | 说明 |
|---|---|---|
max server memory (MB) |
物理内存 - OS(4~8G) - 其他实例 | 最重要,不设会吃光内存导致 OS 卡死 |
min server memory (MB) |
与 max 相同或略低 | 防止内存被 OS 回收导致抖动 |
max degree of parallelism |
8 或 4(NUMA 节点数) | 默认 0(不限)容易引发并行等待 |
cost threshold for parallelism |
50 | 默认 5 太低,小查询也并行 |
optimize for ad hoc workloads |
1 | 减少一次性执行计划的缓存膨胀 |
backup compression default |
1 | 默认压缩备份,省空间省 IO |
max worker threads |
0(自动)或按核数 | 一般不动 |
tempdb 文件数 |
CPU 核数(≤8) | 见第 15 章 |
remote query timeout |
600 | 默认 600 秒 |
default trace enabled |
1 | 排查配置变更的救命数据 |
-- 查看内存使用
SELECT physical_memory_in_use_kb/1024 AS physical_mb,
large_page_allocations_kb/1024 AS large_page_mb,
locked_page_allocations_kb/1024 AS locked_mb,
total_virtual_address_space_kb/1024 AS vas_mb,
virtual_address_space_reserved_kb/1024 AS vas_reserved_mb,
page_fault_count
FROM sys.dm_os_process_memory;
SELECT counter_name, cntr_value
FROM sys.dm_os_performance_counters
WHERE object_name LIKE '%Buffer Manager%' AND counter_name IN ('Total Pages','Database pages','Target pages');
6. 登录名、用户与权限
6.1 登录名(实例级)与用户(库级)
-- 实例级登录名
CREATE LOGIN app WITH PASSWORD = 'App#Str0ng2026', CHECK_POLICY = ON;
CREATE LOGIN app FROM WINDOWS; -- Windows 账号
ALTER LOGIN app WITH PASSWORD = 'New#2026';
ALTER LOGIN app DISABLE;
ALTER LOGIN app ENABLE;
DROP LOGIN app;
-- 查看
SELECT name, type_desc, is_disabled, create_date, default_database_name
FROM sys.server_principals WHERE type IN ('S','U','G');
-- 库级用户(映射到登录名)
USE appdb;
CREATE USER app FOR LOGIN app;
CREATE USER app FOR LOGIN app WITH DEFAULT_SCHEMA = app;
ALTER USER app WITH DEFAULT_SCHEMA = dbo;
DROP USER app;
-- 包含数据库用户(不依赖实例登录名,适合 AG 故障转移)
ALTER DATABASE appdb SET CONTAINMENT = PARTIAL;
CREATE USER app WITH PASSWORD = 'App#2026';
重要:
CREATE LOGIN是实例级、CREATE USER是库级。恢复数据库到另一台实例后经常出现"孤儿用户"(SID对不上),需要用ALTER USER ... WITH LOGIN = ...或sp_change_users_login修复。
6.2 授权
-- 服务器级角色
ALTER SERVER ROLE sysadmin ADD MEMBER app;
ALTER SERVER ROLE securityadmin ADD MEMBER dba;
ALTER SERVER ROLE dbcreator ADD MEMBER app;
SELECT * FROM sys.server_role_members;
-- 数据库级角色
USE appdb;
ALTER ROLE db_datareader ADD MEMBER report;
ALTER ROLE db_datawriter ADD MEMBER app;
ALTER ROLE db_owner ADD MEMBER dba;
ALTER ROLE db_ddladmin ADD MEMBER deploy;
-- 对象级
GRANT SELECT, INSERT, UPDATE, DELETE ON dbo.orders TO app;
GRANT SELECT ON dbo.v_orders TO report;
GRANT EXECUTE ON dbo.p_calc TO app;
DENY DELETE ON dbo.orders TO app; -- DENY 优先于 GRANT
REVOKE SELECT ON dbo.orders FROM report;
-- 查看
SELECT * FROM sys.database_permissions WHERE grantee_principal_id = USER_ID('app');
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
6.3 权限层级
服务器级:登录名 → 服务器角色(sysadmin / securityadmin / dbcreator ...)
数据库级:用户 → 数据库角色(db_owner / db_datareader ...)→ schema → 对象 → 列
注意:SQL Server 的
DENY优先级高于GRANT,且sysadmin成员绕过所有权限检查。排障时先用SELECT IS_SRVROLEMEMBER('sysadmin')确认。
6.4 安全基线
-- 1) 禁用 sa 或改名
ALTER LOGIN sa DISABLE;
-- 或
ALTER LOGIN sa WITH NAME = sysadmin_renamed;
-- 2) 只允许 Windows 认证(若业务允许)
-- SSMS → 服务器属性 → 安全性 → 仅 Windows 身份验证模式
-- 3) 检查空密码/弱密码登录名
SELECT name, is_disabled, is_policy_checked, is_expiration_checked
FROM sys.sql_logins;
-- 4) 强制加密
-- 服务器属性 → 连接 → 强制加密
SELECT session_id, encrypt_option FROM sys.dm_exec_connections WHERE session_id = @@SPID;
-- 5) 审计登录失败
-- SSMS → 安全性 → 审核 → 新建审核 + 服务器审核规范
7. 数据库与文件管理
7.1 库操作
CREATE DATABASE appdb
ON PRIMARY (
NAME = appdb_data, FILENAME = 'D:\MSSQL\Data\appdb.mdf',
SIZE = 1GB, FILEGROWTH = 512MB
)
LOG ON (
NAME = appdb_log, FILENAME = 'E:\MSSQL\Log\appdb.ldf',
SIZE = 2GB, FILEGROWTH = 512MB
);
GO
ALTER DATABASE appdb SET RECOVERY FULL;
ALTER DATABASE appdb SET AUTO_CLOSE OFF;
ALTER DATABASE appdb SET AUTO_SHRINK OFF; -- 必须关,否则性能灾难
ALTER DATABASE appdb SET AUTO_CREATE_STATISTICS ON;
ALTER DATABASE appdb SET AUTO_UPDATE_STATISTICS ON;
ALTER DATABASE appdb SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
ALTER DATABASE appdb SET ALLOW_SNAPSHOT_ISOLATION ON;
ALTER DATABASE appdb MODIFY NAME = appdb2;
ALTER DATABASE appdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE; -- 危险
ALTER DATABASE appdb SET MULTI_USER;
DROP DATABASE appdb; -- 危险
-- 查看
SELECT name, database_id, state_desc, recovery_model_desc, compatibility_level,
containment_desc, is_read_only
FROM sys.databases;
SELECT name, state_desc, user_access_desc, recovery_model_desc
FROM sys.databases WHERE database_id = DB_ID('appdb');
7.2 文件与文件组
-- 加数据文件
ALTER DATABASE appdb ADD FILE (
NAME = appdb_data2, FILENAME = 'D:\MSSQL\Data\appdb2.ndf',
SIZE = 4GB, FILEGROWTH = 1GB
) TO FILEGROUP [PRIMARY];
-- 加文件组(把大表/归档放到独立文件组)
ALTER DATABASE appdb ADD FILEGROUP fg_archive;
ALTER DATABASE appdb ADD FILE (
NAME = appdb_arch, FILENAME = 'F:\MSSQL\Archive\appdb_arch.ndf',
SIZE = 8GB, FILEGROWTH = 1GB
) TO FILEGROUP fg_archive;
-- 迁移表到文件组(重建表)
CREATE UNIQUE CLUSTERED INDEX PK_orders ON dbo.orders(id) WITH (DROP_EXISTING = ON) ON fg_archive;
-- 日志文件
ALTER DATABASE appdb ADD LOG FILE (
NAME = appdb_log2, FILENAME = 'E:\MSSQL\Log\appdb2.ldf',
SIZE = 2GB, FILEGROWTH = 512MB
);
-- 查看
SELECT DB_NAME(database_id) AS db, name, type_desc, physical_name,
size*8/1024 AS size_mb, growth, is_percent_growth, max_size
FROM sys.master_files ORDER BY database_id, file_id;
原则:数据文件与日志文件必须分盘;
FILEGROWTH用固定大小(512MB~1GB),不要用百分比(10% 在大库上会一次增长几十 GB,造成长时间阻塞)。
7.3 表与索引
CREATE TABLE dbo.orders (
id BIGINT IDENTITY(1,1) PRIMARY KEY,
user_id BIGINT NOT NULL,
amount DECIMAL(12,2) NOT NULL DEFAULT 0,
status TINYINT NOT NULL DEFAULT 0,
created_at DATETIME2(3) NOT NULL DEFAULT SYSDATETIME()
);
CREATE NONCLUSTERED INDEX idx_orders_user ON dbo.orders(user_id, created_at)
WITH (ONLINE = ON, FILLFACTOR = 90, DATA_COMPRESSION = PAGE);
-- 只改索引(不锁表,企业版支持 ONLINE)
ALTER INDEX idx_orders_user ON dbo.orders REBUILD WITH (ONLINE = ON);
ALTER INDEX ALL ON dbo.orders REBUILD WITH (ONLINE = ON);
-- 碎片整理建议:10%~30% REORGANIZE,>30% REBUILD
SELECT OBJECT_NAME(ips.object_id) AS table_name, i.name AS index_name,
ips.avg_fragmentation_in_percent, ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON i.object_id = ips.object_id AND i.index_id = ips.index_id
WHERE ips.avg_fragmentation_in_percent > 10 AND ips.page_count > 1000
ORDER BY ips.avg_fragmentation_in_percent DESC;
-- 统计信息
UPDATE STATISTICS dbo.orders WITH FULLSCAN;
UPDATE STATISTICS dbo.orders idx_orders_user WITH SAMPLE 30 PERCENT;
-- 在线索引重建需要企业版;标准版会锁表,必须在维护窗口
-- 大表加列(2022+ 支持部分场景在线)
ALTER TABLE dbo.orders ADD remark NVARCHAR(200) NULL;
7.4 分区表
-- 1) 分区函数与方案
CREATE PARTITION FUNCTION pf_month (DATE)
AS RANGE RIGHT FOR VALUES ('2026-10-01','2026-11-01','2026-12-01');
CREATE PARTITION SCHEME ps_month AS PARTITION pf_month ALL TO ([PRIMARY]);
-- 2) 建分区表
CREATE TABLE dbo.logs (
id BIGINT IDENTITY, log_date DATE NOT NULL, msg NVARCHAR(1000)
) ON ps_month(log_date);
-- 3) 加分区(SPLIT)
ALTER PARTITION SCHEME ps_month NEXT USED [PRIMARY];
ALTER PARTITION FUNCTION pf_month() SPLIT RANGE ('2027-01-01');
-- 4) 归档:切出分区到独立表(秒级)
CREATE TABLE dbo.logs_202610 (LIKE dbo.logs) ON [PRIMARY];
ALTER TABLE dbo.logs SWITCH PARTITION 2 TO dbo.logs_202610;
-- 5) 合并分区
ALTER PARTITION FUNCTION pf_month() MERGE RANGE ('2026-10-01');
-- 查看
SELECT $PARTITION.pf_month('2026-11-15') AS partition_number;
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.logs');
8. 恢复模式与日志管理
8.1 三种恢复模式
| 模式 | 日志行为 | 能否 PITR | 适用 |
|---|---|---|---|
SIMPLE |
自动截断,不保留 | 否 | 测试库、可容忍丢当天数据 |
FULL |
保留到日志备份 | 是 | 生产标准 |
BULK_LOGGED |
大容量操作最小记录 | 部分 | 批量导入期间临时切换 |
ALTER DATABASE appdb SET RECOVERY FULL;
ALTER DATABASE appdb SET RECOVERY SIMPLE;
SELECT name, recovery_model_desc, log_reuse_wait_desc FROM sys.databases;
关键点:切到
FULL后必须立刻做一次全备,否则日志会一直增长不截断(因为没有日志备份链的起点)。
8.2 日志为什么不截断
SELECT name, log_reuse_wait_desc FROM sys.databases;
log_reuse_wait_desc |
含义 | 处理 |
|---|---|---|
NOTHING |
正常 | — |
LOG_BACKUP |
等待日志备份 | 做日志备份 |
CHECKPOINT |
等待检查点 | 通常自动 |
ACTIVE_TRANSACTION |
有长事务 | 找并处理 |
REPLICATION |
复制未分发 | 检查分发代理 |
AVAILABILITY_REPLICA |
AG 副本未收到日志 | 检查 AG 同步 |
DATABASE_MIRRORING |
镜像滞后 | 检查镜像 |
OLDEST_PAGE |
最老页未备份 | 做差异/全备 |
XTP_CHECKPOINT |
内存优化表 | — |
-- 空间占用
DBCC SQLPERF(LOGSPACE);
-- 日志文件大小与使用
SELECT DB_NAME(database_id) AS db, name, size*8/1024 AS size_mb,
FILEPROPERTY(name,'SpaceUsed')*8/1024 AS used_mb
FROM sys.master_files WHERE type_desc = 'LOG';
8.3 日志收缩(谨慎)
-- 1) 确认是 FULL 且有长事务
SELECT log_reuse_wait_desc FROM sys.databases WHERE name='appdb';
-- 2) 做日志备份(截断)
BACKUP LOG appdb TO DISK = 'F:\MSSQL\Backup\appdb_log.trn' WITH COMPRESSION;
-- 3) 收缩到目标大小(不要用 DBCC SHRINKDATABASE)
DBCC SHRINKFILE (appdb_log, 2048); -- 单位 MB
-- 4) 设合理初始大小与增长
ALTER DATABASE appdb MODIFY FILE (NAME = appdb_log, SIZE = 4GB, FILEGROWTH = 512MB);
危险:
DBCC SHRINKDATABASE会收缩所有文件并产生大量碎片,生产禁用。日志频繁爆满的根因通常是"没做日志备份"或"一次大事务",收缩只是治标。
9. 备份与恢复
9.1 备份类型
| 类型 | 命令 | 说明 |
|---|---|---|
| 完整备份 | BACKUP DATABASE |
备份链起点 |
| 差异备份 | BACKUP DATABASE ... WITH DIFFERENTIAL |
基于最近一次全备 |
| 事务日志备份 | BACKUP LOG |
仅 FULL/BULK_LOGGED,支持 PITR |
| 文件/文件组备份 | BACKUP DATABASE ... FILE = ... |
超大库分片 |
| 尾日志备份 | BACKUP LOG ... WITH NORECOVERY |
灾难时抢救最后一段 |
9.2 备份命令
-- 完整备份(带校验与压缩,覆盖旧文件)
BACKUP DATABASE appdb
TO DISK = 'F:\MSSQL\Backup\appdb_full_20261105.bak'
WITH INIT, COMPRESSION, CHECKSUM, STATS = 10,
NAME = 'appdb full backup';
-- 差异备份
BACKUP DATABASE appdb
TO DISK = 'F:\MSSQL\Backup\appdb_diff_20261105.bak'
WITH INIT, DIFFERENTIAL, COMPRESSION, CHECKSUM;
-- 日志备份
BACKUP LOG appdb
TO DISK = 'F:\MSSQL\Backup\appdb_log_20261105_1200.trn'
WITH INIT, COMPRESSION, CHECKSUM;
-- 备份到多个文件(并行)
BACKUP DATABASE appdb
TO DISK = 'F:\B\appdb_1.bak', DISK = 'G:\B\appdb_2.bak'
WITH INIT, COMPRESSION;
-- 尾日志(数据库损坏时抢救)
BACKUP LOG appdb TO DISK = 'F:\B\tail.trn' WITH NORECOVERY, INIT;
-- 验证备份(不恢复,只校验可读性)
RESTORE VERIFYONLY FROM DISK = 'F:\MSSQL\Backup\appdb_full_20261105.bak' WITH CHECKSUM;
-- 查看备份内容
RESTORE HEADERONLY FROM DISK = 'F:\MSSQL\Backup\appdb_full_20261105.bak';
RESTORE FILELISTONLY FROM DISK = 'F:\MSSQL\Backup\appdb_full_20261105.bak';
-- 备份历史
SELECT database_name, type, backup_start_date, backup_finish_date,
backup_size/1024/1024 AS size_mb, compressed_backup_size/1024/1024 AS comp_mb,
physical_device_name
FROM msdb.dbo.backupset bs
JOIN msdb.dbo.backupmediafamily mf ON mf.media_set_id = bs.media_set_id
WHERE database_name = 'appdb'
ORDER BY backup_start_date DESC;
9.3 恢复
-- 1) 查看备份中的逻辑文件名
RESTORE FILELISTONLY FROM DISK = 'F:\MSSQL\Backup\appdb_full_20261105.bak';
-- 2) 完整恢复(覆盖现有库)
RESTORE DATABASE appdb
FROM DISK = 'F:\MSSQL\Backup\appdb_full_20261105.bak'
WITH REPLACE, RECOVERY, STATS = 10,
MOVE 'appdb_data' TO 'D:\MSSQL\Data\appdb.mdf',
MOVE 'appdb_log' TO 'E:\MSSQL\Log\appdb.ldf';
-- 3) 恢复到中间状态(准备继续应用日志)
RESTORE DATABASE appdb FROM DISK = '...full.bak' WITH NORECOVERY, REPLACE;
RESTORE DATABASE appdb FROM DISK = '...diff.bak' WITH NORECOVERY;
RESTORE LOG appdb FROM DISK = '...log1.trn' WITH NORECOVERY;
RESTORE LOG appdb FROM DISK = '...log2.trn' WITH RECOVERY;
-- 4) 时间点恢复
RESTORE DATABASE appdb FROM DISK = '...full.bak' WITH NORECOVERY, REPLACE;
RESTORE LOG appdb FROM DISK = '...log.trn'
WITH RECOVERY, STOPAT = '2026-11-05T10:15:00';
-- 5) 只恢复某张表(恢复到临时库再导)
RESTORE DATABASE appdb_restore FROM DISK = '...full.bak'
WITH REPLACE, RECOVERY,
MOVE 'appdb_data' TO 'D:\MSSQL\Data\appdb_restore.mdf',
MOVE 'appdb_log' TO 'E:\MSSQL\Log\appdb_restore.ldf';
-- 然后 INSERT INTO appdb.dbo.orders SELECT * FROM appdb_restore.dbo.orders
顺序不能错:全备 → 差异(可选)→ 日志(按 LSN 顺序,一个不能少)→ 最后一次用
WITH RECOVERY。中间任何一步用了RECOVERY,后续日志就无法再应用。
9.4 备份策略模板
| 库类型 | 全备 | 差异 | 日志 | 保留 |
|---|---|---|---|---|
| 核心交易库 | 每日 1 次 | 每 4 小时 | 每 15 分钟 | 30 天 |
| 一般业务库 | 每日 1 次 | 每 6 小时 | 每 1 小时 | 14 天 |
| 报表/只读库 | 每周 1 次 | 每日 | 不需要(SIMPLE) | 30 天 |
-- 用维护计划或 SQL Agent 作业串起来
-- 作业步骤示例
BACKUP DATABASE appdb TO DISK = 'F:\B\appdb_full_' + FORMAT(GETDATE(),'yyyyMMdd') + '.bak'
WITH INIT, COMPRESSION, CHECKSUM;
9.5 Ola Hallengren 维护脚本(业界标准)
大多数生产环境用 Ola 的脚本统一管理备份、索引与完整性检查:
EXEC master.dbo.DatabaseBackup
@Databases = 'USER_DATABASES',
@Directory = 'F:\MSSQL\Backup',
@BackupType = 'FULL',
@Verify = 'Y',
@Compress = 'Y',
@CheckSum = 'Y',
@CleanupTime = 720; -- 保留 30 天
EXEC master.dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REORGANIZE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE',
@FragmentationLevel1 = 10,
@FragmentationLevel2 = 30;
10. 高可用:Always On 与日志传送
10.1 方案对比
| 方案 | 故障切换 | 只读副本 | 版本要求 |
|---|---|---|---|
| Always On 可用性组(AG) | 自动/手动 | 支持 | Enterprise(Standard 限 2 副本、无只读) |
| 故障转移群集(FCI) | 自动 | 不支持 | 全版本 |
| 日志传送 | 手动 | 可(需还原为 STANDBY) | 全版本 |
| 数据库镜像 | 自动 | 快照 | 已弃用,不要新上 |
10.2 Always On 状态查询
-- 可用性组
SELECT ag.name AS ag_name, ag.automated_backup_preference_desc,
ar.replica_server_name, ar.availability_mode_desc, ar.failover_mode_desc,
ars.role_desc, ars.synchronization_health_desc, ars.connected_state_desc
FROM sys.availability_groups ag
JOIN sys.availability_replicas ar ON ar.group_id = ag.group_id
JOIN sys.dm_hadr_availability_replica_states ars ON ars.replica_id = ar.replica_id;
-- 数据库级同步状态(关键:log_send_queue_size / redo_queue_size)
SELECT ag.name AS ag_name, adc.database_name, drs.synchronization_state_desc,
drs.log_send_queue_size AS send_queue_kb,
drs.log_send_rate AS send_rate_kb_s,
drs.redo_queue_size AS redo_queue_kb,
drs.redo_rate AS redo_rate_kb_s
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_databases_cluster adc ON adc.group_database_id = drs.group_database_id
JOIN sys.availability_groups ag ON ag.group_id = drs.group_id;
-- 副本延迟
SELECT replica_server_name, last_connect_error_number, last_connect_error_description
FROM sys.dm_hadr_availability_replica_states ars
JOIN sys.availability_replicas ar ON ar.replica_id = ars.replica_id
WHERE ars.last_connect_error_number IS NOT NULL;
10.3 手动切换
-- 主副本上
ALTER AVAILABILITY GROUP AG_APP FAILOVER;
-- 检查是否可切换
SELECT ag.name, ar.replica_server_name, ars.role_desc, ars.synchronization_health_desc,
ars.is_local
FROM sys.dm_hadr_availability_replica_states ars
JOIN sys.availability_replicas ar ON ar.replica_id = ars.replica_id
JOIN sys.availability_groups ag ON ag.group_id = ar.group_id;
-- 暂停/恢复数据移动(维护副本时)
ALTER AVAILABILITY GROUP AG_APP SUSPEND;
ALTER AVAILABILITY GROUP AG_APP RESUME;
10.4 日志传送
-- 主库配置(备份作业)
BACKUP LOG appdb TO DISK = '\\share\logship\appdb.trn' WITH INIT;
-- 辅助库还原作业
RESTORE LOG appdb FROM DISK = '\\share\logship\appdb.trn' WITH NORECOVERY;
-- 查看历史与延迟
SELECT * FROM msdb.dbo.log_shipping_monitor_primary;
SELECT * FROM msdb.dbo.log_shipping_monitor_secondary;
注意:日志传送的还原作业必须用
WITH NORECOVERY(或STANDBY以便只读查询)。用RECOVERY后下一个日志就无法应用。
11. 日志体系与错误排查
11.1 错误日志
-- 读取错误日志(0 = 当前,1 = 归档 1,...)
EXEC sp_readerrorlog;
EXEC sp_readerrorlog 0, 1, N'error';
EXEC sp_readerrorlog 0, 1, N'Login failed';
EXEC sp_readerrorlog 0, 1, N'deadlock';
-- 循环所有日志
EXEC sp_cycle_errorlog; -- 手工轮转
SELECT COUNT(*) FROM sys.dm_os_server_diagnostics_log_configurations;
# Linux 路径
ls /var/opt/mssql/log/
tail -f /var/opt/mssql/log/errorlog
11.2 默认跟踪(配置变更审计)
-- 默认跟踪文件位置
SELECT * FROM sys.traces WHERE is_default = 1;
-- 读最近的对象创建/删除/权限变更
SELECT te.name AS event_name, t.DatabaseName, t.ObjectName, t.LoginName,
t.StartTime, t.ApplicationName
FROM sys.fn_trace_gettable(
(SELECT REVERSE(SUBSTRING(REVERSE(path), CHARINDEX('\', REVERSE(path)), 256))
+ 'log.trc' FROM sys.traces WHERE is_default = 1), DEFAULT) t
JOIN sys.trace_events te ON te.trace_event_id = t.EventClass
WHERE te.name IN ('Object:Created','Object:Deleted','Object:Altered')
ORDER BY t.StartTime DESC;
11.3 Extended Events
-- 现成会话:system_health(死锁、严重错误都记在里面)
SELECT xet.name, xes.event_name, xes.package_name
FROM sys.dm_xe_session_events xes
JOIN sys.dm_xe_sessions xet ON xet.address = xes.event_session_address
WHERE xet.name = 'system_health';
-- 读 system_health 里的死锁
SELECT CAST(event_data AS XML) AS deadlock_xml
FROM sys.fn_xe_file_target_read_file('system_health*.xel', NULL, NULL, NULL)
WHERE object_name = 'xml_deadlock_report';
-- 建一个慢查询捕获会话
CREATE EVENT SESSION [slow_queries] ON SERVER
ADD EVENT sqlserver.sql_statement_completed (
ACTION (sqlserver.sql_text, sqlserver.database_name, sqlserver.username)
WHERE duration > 5000000 -- 微秒,即 5 秒
)
ADD TARGET package0.event_file (SET filename = 'F:\XE\slow_queries.xel', max_file_size = 256);
GO
ALTER EVENT SESSION [slow_queries] ON SERVER STATE = START;
-- 读文件目标
SELECT CAST(event_data AS XML).value('(event/@name)[1]','varchar(100)') AS event,
CAST(event_data AS XML).value('(event/data[@name="duration"]/value)[1]','bigint')/1000000 AS seconds,
CAST(event_data AS XML).value('(event/action[@name="sql_text"]/value)[1]','varchar(max)') AS sql
FROM sys.fn_xe_file_target_read_file('F:\XE\slow_queries*.xel', NULL, NULL, NULL);
11.4 日志清理
-- 错误日志默认 6 个,循环即可(不要手工删文件)
EXEC sp_cycle_errorlog;
# Linux:logrotate 或按需清理
du -sh /var/opt/mssql/log/*
12. 性能诊断:DMV 与 Query Store
12.1 一眼看现状
SELECT @@SERVERNAME AS server_name,
sqlserver_start_time,
DATEDIFF(HOUR, sqlserver_start_time, GETDATE()) AS uptime_hours
FROM sys.dm_os_sys_info;
-- 连接数
SELECT COUNT(*) AS sessions,
SUM(CASE WHEN status = 'running' THEN 1 ELSE 0 END) AS running,
SUM(CASE WHEN status = 'sleeping' THEN 1 ELSE 0 END) AS sleeping
FROM sys.dm_exec_sessions WHERE is_user_process = 1;
-- 内存
SELECT physical_memory_in_use_kb/1024 AS used_mb,
(SELECT cntr_value/1024 FROM sys.dm_os_performance_counters
WHERE counter_name = 'Target Server Memory (KB)') AS target_mb
FROM sys.dm_os_process_memory;
12.2 当前请求
SELECT r.session_id, r.status, r.command, r.wait_type, r.wait_time, r.blocking_session_id,
r.cpu_time, r.total_elapsed_time/1000 AS elapsed_sec,
r.logical_reads, r.reads, r.writes,
DB_NAME(r.database_id) AS db,
SUBSTRING(t.text, (r.statement_start_offset/2)+1,
((CASE r.statement_end_offset WHEN -1 THEN DATALENGTH(t.text)
ELSE r.statement_end_offset END - r.statement_start_offset)/2)+1) AS current_statement,
t.text AS full_batch
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.session_id > 50 AND r.session_id <> @@SPID
ORDER BY r.total_elapsed_time DESC;
-- sp_who2 快速版
EXEC sp_who2;
EXEC sp_who2 'active';
12.3 等待统计
SELECT TOP 15 wait_type,
wait_time_ms/1000 AS wait_sec,
waiting_tasks_count,
wait_time_ms/NULLIF(waiting_tasks_count,0) AS avg_wait_ms,
signal_wait_time_ms/1000 AS signal_sec
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
'SLEEP_TASK','BROKER_TASK_STOP','SQLTRACE_BUFFER_FLUSH','CLR_AUTO_EVENT',
'LAZYWRITER_SLEEP','CHECKPOINT_QUEUE','XE_TIMER_EVENT','WAITFOR',
'BROKER_TO_FLUSH','HADR_FILESTREAM_IOMGR_IOCOMPLETION','DIRTY_PAGE_POLL')
ORDER BY wait_time_ms DESC;
常见等待类型对照:
| wait_type | 含义 | 方向 |
|---|---|---|
CXPACKET / CXCONSUMER |
并行执行倾斜 | 调 MAXDOP、cost threshold |
PAGEIOLATCH_SH/EX |
读页等待磁盘 | 内存不足或 IO 慢 |
WRITELOG |
等日志写盘 | 日志盘性能、提交频繁 |
LCK_M_* |
锁等待 | 阻塞、事务过长 |
RESOURCE_SEMAPHORE |
等内存授予 | 内存不足、坏计划 |
ASYNC_NETWORK_IO |
等客户端接收 | 应用取数慢、网络 |
SOS_SCHEDULER_YIELD |
CPU 压力 | CPU 瓶颈 |
THREADPOOL |
工作线程耗尽 | 阻塞雪崩、max worker threads |
PREEMPTIVE_OS_* |
外部 OS 调用 | 文件/网络/认证 |
12.4 高开销 SQL
SELECT TOP 20
qs.execution_count,
qs.total_worker_time/1000 AS total_cpu_ms,
qs.total_worker_time/NULLIF(qs.execution_count,0)/1000 AS avg_cpu_ms,
qs.total_elapsed_time/1000 AS total_elapsed_ms,
qs.total_logical_reads,
qs.total_logical_reads/NULLIF(qs.execution_count,0) AS avg_reads,
SUBSTRING(t.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(t.text)
ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) AS statement,
qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) t
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_worker_time DESC;
12.5 执行计划与统计 IO
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SET SHOWPLAN_ALL OFF;
SELECT * FROM dbo.orders WHERE user_id = 100;
-- 输出:logical reads / physical reads / 编译与执行时间
-- 实际执行计划
SET STATISTICS PROFILE ON;
-- 或 SET STATISTICS XML ON,SSMS 里点"包含实际执行计划"
关键判读:
| 现象 | 含义 |
|---|---|
Table Scan / Clustered Index Scan 大表 |
缺索引或索引未命中 |
Key Lookup 很多 |
非覆盖索引,考虑 INCLUDE 列 |
| 预估行数与实际差 100 倍 | 统计信息过期或参数嗅探 |
Sort / Hash Match 溢出到 tempdb |
内存授予不足 |
| 并行运算符倾斜(某一线程行数远超其他) | MAXDOP 或数据分布问题 |
12.6 Query Store(2016+,强烈建议开)
ALTER DATABASE appdb SET QUERY_STORE = ON;
ALTER DATABASE appdb SET QUERY_STORE (
OPERATION_MODE = READ_WRITE,
DATA_FLUSH_INTERVAL_SECONDS = 900,
INTERVAL_LENGTH_MINUTES = 60,
MAX_STORAGE_SIZE_MB = 2048,
QUERY_CAPTURE_MODE = AUTO,
SIZE_BASED_CLEANUP_MODE = AUTO);
-- 查找回归的查询(计划变差)
SELECT q.query_id, qt.query_sql_text,
p.plan_id, rs.avg_duration/1000 AS avg_ms, rs.count_executions,
rs.last_execution_time
FROM sys.query_store_query q
JOIN sys.query_store_query_text qt ON qt.query_text_id = q.query_text_id
JOIN sys.query_store_plan p ON p.query_id = q.query_id
JOIN sys.query_store_runtime_stats rs ON rs.plan_id = p.plan_id
WHERE q.query_id IN (
SELECT query_id FROM sys.query_store_plan
GROUP BY query_id HAVING COUNT(DISTINCT plan_id) > 1)
ORDER BY rs.last_execution_time DESC;
-- 强制使用某个计划(治计划回归最快的手段)
EXEC sp_query_store_force_plan @query_id = 123, @plan_id = 456;
EXEC sp_query_store_unforce_plan @query_id = 123, @plan_id = 456;
12.7 索引使用分析
-- 从未被使用的索引(写放大元凶)
SELECT OBJECT_NAME(i.object_id) AS table_name, i.name AS index_name,
ius.user_seeks, ius.user_scans, ius.user_lookups, ius.user_updates
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats ius
ON ius.object_id = i.object_id AND ius.index_id = i.index_id
AND ius.database_id = DB_ID()
WHERE i.object_id > 100 AND i.type > 1
AND ISNULL(ius.user_seeks,0) + ISNULL(ius.user_scans,0) + ISNULL(ius.user_lookups,0) = 0
AND ISNULL(ius.user_updates,0) > 0
ORDER BY ius.user_updates DESC;
-- 缺失索引建议(只作参考,不要全盘照搬)
SELECT TOP 20
ROUND(s.avg_total_user_cost * s.avg_user_impact * (s.user_seeks + s.user_scans), 0) AS score,
s.avg_user_impact, s.user_seeks, s.user_scans,
d.statement AS table_name, d.equality_columns, d.inequality_columns, d.included_columns
FROM sys.dm_db_missing_index_group_stats s
JOIN sys.dm_db_missing_index_groups g ON g.index_group_handle = s.group_handle
JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle
WHERE d.database_id = DB_ID()
ORDER BY score DESC;
注意:缺失索引 DMV 在实例重启后清空,且不懂列顺序与写成本。它给的是"候选",落地前要自己评估选择性、写放大与索引数量上限(一般单表不超 5~6 个)。
13. 锁、阻塞与死锁
13.1 阻塞定位
-- 当前阻塞链
SELECT r.session_id, r.blocking_session_id, r.wait_type, r.wait_time,
r.status, r.command, DB_NAME(r.database_id) AS db,
SUBSTRING(t.text, 1, 200) AS sql
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.blocking_session_id <> 0;
-- 阻塞树(递归)
WITH blockers AS (
SELECT session_id, blocking_session_id, 1 AS level
FROM sys.dm_exec_requests WHERE blocking_session_id <> 0
UNION ALL
SELECT b.session_id, b.blocking_session_id, level + 1
FROM sys.dm_exec_requests b
JOIN blockers c ON c.blocking_session_id = b.session_id
WHERE b.blocking_session_id <> 0 AND level < 10
)
SELECT * FROM blockers ORDER BY level, session_id;
-- 锁明细
SELECT request_session_id, resource_type, resource_database_id,
DB_NAME(resource_database_id) AS db, resource_description,
request_mode, request_status
FROM sys.dm_tran_locks
WHERE request_status = 'WAIT';
-- 打开的事务
SELECT tat.transaction_id, tat.name, tat.transaction_begin_time,
DATEDIFF(SECOND, tat.transaction_begin_time, GETDATE()) AS age_sec,
ts.session_id, ts.status
FROM sys.dm_tran_active_transactions tat
JOIN sys.dm_tran_session_transactions ts ON ts.transaction_id = tat.transaction_id;
13.2 处理阻塞
-- 先看被阻塞者在等什么,再决定杀谁
EXEC sp_who2 'active';
-- 温和:杀掉语句所在会话(无"只杀语句"的官方命令,只能杀整个会话)
KILL 123;
KILL 123 WITH STATUSONLY; -- 查看回滚进度
注意:SQL Server 没有 Oracle 的
KILL QUERY等价物,KILL就是杀整个会话并回滚事务。大事务回滚可能比执行更久,KILL ... WITH STATUSONLY可以看进度。
13.3 死锁
-- 1) 开跟踪标志 1222,死锁写入 errorlog
DBCC TRACEON (1222, -1);
-- 2) 从 system_health 读死锁图
SELECT CAST(event_data AS XML) AS deadlock_xml
FROM sys.fn_xe_file_target_read_file('system_health*.xel', NULL, NULL, NULL)
WHERE object_name = 'xml_deadlock_report';
-- 3) 从 errorlog 读
EXEC sp_readerrorlog 0, 1, N'deadlock';
死锁的四个常见成因与对策:
| 成因 | 对策 |
|---|---|
| 两表更新顺序相反 | 统一业务层的加锁顺序 |
| 缺少索引导致锁范围扩大 | 补索引,缩小扫描范围 |
| 长事务持有锁 | 缩短事务,避免事务里等用户输入 |
| 隔离级别过高 | 评估 READ_COMMITTED_SNAPSHOT |
-- 开启 RCSI(读不阻塞写),需短暂排他
ALTER DATABASE appdb SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
14. 空间与容量管理
14.1 库与表大小
-- 所有库的大小
SELECT DB_NAME(database_id) AS db,
SUM(CASE WHEN type_desc = 'ROWS' THEN size END)*8/1024 AS data_mb,
SUM(CASE WHEN type_desc = 'LOG' THEN size END)*8/1024 AS log_mb
FROM sys.master_files GROUP BY database_id ORDER BY data_mb DESC;
-- 当前库表大小(sp_spaceused)
EXEC sp_spaceused;
EXEC sp_spaceused 'dbo.orders';
-- 精确到表(含索引)
SELECT t.name AS table_name,
SUM(a.total_pages)*8/1024 AS total_mb,
SUM(a.used_pages)*8/1024 AS used_mb,
SUM(a.data_pages)*8/1024 AS data_mb
FROM sys.tables t
JOIN sys.indexes i ON i.object_id = t.object_id
JOIN sys.partitions p ON p.object_id = t.object_id AND p.index_id = i.index_id
JOIN sys.allocation_units a ON a.container_id = p.partition_id
GROUP BY t.name ORDER BY total_mb DESC;
-- 磁盘余量
SELECT DISTINCT volume_mount_point, file_system_type,
total_bytes/1024/1024/1024 AS total_gb,
available_bytes/1024/1024/1024 AS free_gb
FROM sys.master_files
CROSS APPLY sys.dm_os_volume_stats(database_id, file_id);
14.2 数据文件收缩
-- 先看可回收空间
SELECT DB_NAME(database_id) AS db, name, size*8/1024 AS size_mb,
FILEPROPERTY(name,'SpaceUsed')*8/1024 AS used_mb
FROM sys.master_files WHERE type_desc = 'ROWS';
-- 收缩单个文件到目标大小
DBCC SHRINKFILE (appdb_data, 8192); -- 8GB
-- 只收缩到不产生碎片的最小值
DBCC SHRINKFILE (appdb_data, 0, TRUNCATEONLY);
危险:
DBCC SHRINKDATABASE与频繁SHRINKFILE会造成严重索引碎片与 IO 抖动,生产上应"一次设足初始大小 + 固定增长",而不是反复收缩。
14.3 空间增长规划
-- 关闭自动收缩、设置固定增长
ALTER DATABASE appdb SET AUTO_SHRINK OFF;
ALTER DATABASE appdb MODIFY FILE (
NAME = appdb_data, SIZE = 16GB, FILEGROWTH = 1024MB, MAXSIZE = UNLIMITED);
ALTER DATABASE appdb MODIFY FILE (
NAME = appdb_log, SIZE = 8GB, FILEGROWTH = 512MB);
14.4 大表归档
-- 分批删除,避免日志暴涨与长时间锁
WHILE 1 = 1
BEGIN
DELETE TOP (5000) FROM dbo.logs WHERE log_date < '2026-01-01';
IF @@ROWCOUNT = 0 BREAK;
CHECKPOINT; -- FULL 模式下仍需日志备份配合
WAITFOR DELAY '00:00:01';
END
-- 或在 SIMPLE 模式下用 SWITCH 分区秒级归档(见 7.4)
15. tempdb 与内存管理
15.1 tempdb 配置
-- 查看
SELECT name, physical_name, size*8/1024 AS size_mb, growth, is_percent_growth
FROM tempdb.sys.database_files;
-- 建议:数据文件数 = CPU 核数(≤8),每个文件等大,固定增长
ALTER DATABASE tempdb MODIFY FILE (NAME = tempdev, SIZE = 4GB, FILEGROWTH = 512MB);
ALTER DATABASE tempdb ADD FILE (
NAME = tempdev2, FILENAME = 'T:\MSSQL\tempdb\tempdb2.ndf', SIZE = 4GB, FILEGROWTH = 512MB);
-- 重启后 tempdb 恢复到设定大小(2019+ 可用 MEMORY_OPTIMIZED 元数据)
关键:tempdb 每次重启重建,初始大小要设足(否则每次重启后先经历一轮增长)。文件数超过 8 个对多数场景无收益。
15.2 tempdb 争用
-- PAGELATCH 等待集中在 2:1:1 / 2:1:3 等页
SELECT session_id, wait_type, resource_description, wait_duration_ms
FROM sys.dm_os_waiting_tasks
WHERE wait_type LIKE 'PAGELATCH%' AND resource_description LIKE '2:%';
-- 2019+ 的元数据优化与 tempdb 配置
SELECT name, value_in_use FROM sys.configurations
WHERE name IN ('tempdb metadata memory-optimized');
15.3 内存
-- 各库缓存占用
SELECT COUNT(*) * 8 / 1024 AS cached_mb, DB_NAME(database_id) AS db
FROM sys.dm_os_buffer_descriptors
GROUP BY database_id ORDER BY cached_mb DESC;
-- 内存授予等待
SELECT waiting_tasks_count, wait_time_ms/1000 AS wait_sec
FROM sys.dm_os_wait_stats WHERE wait_type = 'RESOURCE_SEMAPHORE';
-- 清缓存(仅测试环境,生产禁止)
-- DBCC FREEPROCCACHE;
-- DBCC DROPCLEANBUFFERS;
危险:
DBCC DROPCLEANBUFFERS会清空数据缓存,生产执行后所有查询直接打盘,可能引发雪崩。只在性能测试时用。
16. 升级、迁移与补丁
16.1 支持路径
| 场景 | 支持情况 |
|---|---|
| 2016 → 2019/2022 | 支持就地升级 |
| 2017 → 2022/2025 | 支持就地升级 |
| 2019 → 2025 | 支持就地升级 |
| 跨两个大版本 | 需逐级,或导出导入 |
| 降级 | 不支持,只能恢复旧版备份或导出导入 |
16.2 升级前检查
-- 1) 版本与补丁
SELECT @@VERSION, SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition');
-- 2) 兼容级别(升级后默认仍是旧级别,需手动提升)
SELECT name, compatibility_level FROM sys.databases;
-- 3) 已弃用功能
SELECT * FROM sys.dm_os_performance_counters WHERE object_name LIKE '%Deprecated%';
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure;
-- 4) 升级顾问(Microsoft/Assessment 工具)或 Data Migration Assistant
-- 5) 无效对象与跨库依赖
SELECT * FROM sys.sql_expression_dependencies WHERE is_schema_bound_reference = 0;
# Linux 升级(换仓库版本后)
dnf update -y mssql-server
systemctl restart mssql-server
16.3 升级后
-- 1) 提升兼容级别(先测试!)
ALTER DATABASE appdb SET COMPATIBILITY_LEVEL = 170; -- 2025 对应 170,2022 对应 160
-- 2) 更新统计信息
EXEC sp_updatestats;
-- 3) 检查 DBCC CHECKDB
DBCC CHECKDB ('appdb') WITH NO_INFOMSGS, ALL_ERRORMSGS;
-- 4) 重建索引(可选,升级后碎片可能变化)
-- 5) 验证 Agent 作业、链接服务器、SSIS 包、备份计划
注意:升级只改引擎版本,不改兼容级别。新版本的优化器行为要等你手动提升
COMPATIBILITY_LEVEL才启用。提升前务必在测试库跑 Query Store 回归对比。
16.4 迁移(跨实例/跨云)
| 方式 | 适用 | 停机 |
|---|---|---|
| 备份/还原 | 同版本或低→高 | 中 |
| 分离/附加 | 同版本、可停机 | 短 |
| 生成脚本 + BCP/导入导出 | 跨版本、小库 | 长 |
| Always On / 日志传送 | 大库、要求低停机 | 极短 |
| Azure Data Migration Assistant | 评估 + 迁移 | 视方案 |
-- 分离与附加
EXEC sp_detach_db 'appdb';
CREATE DATABASE appdb ON (FILENAME='D:\MSSQL\Data\appdb.mdf'), (FILENAME='E:\MSSQL\Log\appdb.ldf')
FOR ATTACH;
-- 只读打开(用于抢救)
CREATE DATABASE appdb ON (FILENAME='...mdf') FOR ATTACH_REBUILD_LOG;
17. 高频故障速查
17.1 连不上
| 现象/错误 | 排查 |
|---|---|
| 错误 18456 登录失败 | 密码错 / 账号禁用 / 仅 Windows 认证 / 默认库不可用 |
| 错误 4060 无法打开数据库 | 库不存在、离线、无权限、默认库被删 |
| 错误 233 / 258 | TLS 版本不匹配 / 防火墙 / 端口 |
| 错误 1225 | 未启用 TCP/IP 协议 |
| 错误 53 | 实例名或主机名解析失败 |
sa 登录被拒 |
混合模式未开,或 sa 被禁用 |
-- 看详细失败原因
EXEC sp_readerrorlog 0, 1, N'Login failed';
-- 确认认证模式(1=仅 Windows)
SELECT SERVERPROPERTY('IsIntegratedSecurityOnly');
-- 确认账号状态
SELECT name, is_disabled, is_policy_checked FROM sys.sql_logins WHERE name='sa';
# Linux 确认监听
ss -lntp | grep 1433
grep -i 'listening' /var/opt/mssql/log/errorlog
17.2 数据库变成 RECOVERY_PENDING / SUSPECT
SELECT name, state_desc FROM sys.databases;
| 状态 | 含义 | 处理 |
|---|---|---|
RECOVERY_PENDING |
资源不可用(文件缺失/权限) | 修文件路径或权限,ALTER DATABASE ... SET ONLINE |
SUSPECT |
严重损坏 | 从备份恢复,或 EMERGENCY 模式抢救 |
OFFLINE |
手工离线 | ALTER DATABASE ... SET ONLINE |
RESTORING |
正在还原 | 继续应用日志或 WITH RECOVERY |
-- 紧急模式抢救(最后手段)
ALTER DATABASE appdb SET EMERGENCY;
ALTER DATABASE appdb SET SINGLE_USER;
DBCC CHECKDB ('appdb', REPAIR_ALLOW_DATA_LOSS); -- 可能丢数据
ALTER DATABASE appdb SET MULTI_USER;
ALTER DATABASE appdb SET ONLINE;
危险:
REPAIR_ALLOW_DATA_LOSS会删除损坏页上的数据,只在没有备份、必须救活时用。执行前先复制 mdf/ldf 文件留底。
17.3 日志满 / 无法增长
SELECT name, log_reuse_wait_desc FROM sys.databases WHERE name='appdb';
DBCC SQLPERF(LOGSPACE);
-- 急救(有备份前提下)
BACKUP LOG appdb TO DISK='F:\B\appdb_log_emergency.trn' WITH INIT, COMPRESSION;
DBCC SHRINKFILE (appdb_log, 2048);
根治:FULL 模式下配日志备份作业(15 分钟一次);或确认业务可容忍后改 SIMPLE。
17.4 阻塞雪崩
EXEC sp_who2 'active';
SELECT session_id, blocking_session_id, wait_type, wait_time, DB_NAME(database_id)
FROM sys.dm_exec_requests WHERE blocking_session_id <> 0;
处理顺序:找到最源头的阻塞会话(blocking_session_id = 0 的那个)→ 判断是长事务还是坏查询 → 联系业务或 KILL。
17.5 CPU 100%
-- TOP CPU 查询
SELECT TOP 10 qs.total_worker_time/1000 AS cpu_ms, qs.execution_count,
qs.total_worker_time/NULLIF(qs.execution_count,0)/1000 AS avg_cpu_ms,
SUBSTRING(t.text,1,150) AS sql
FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) t
ORDER BY qs.total_worker_time DESC;
-- 当前在跑的
SELECT session_id, cpu_time, status, command FROM sys.dm_exec_requests ORDER BY cpu_time DESC;
常见原因:并行度过高(MAXDOP=0)、缺失索引导致全表扫、参数嗅探、CXPACKET 倾斜。
17.6 内存不足
SELECT object_name, counter_name, cntr_value
FROM sys.dm_os_performance_counters
WHERE counter_name IN ('Page life expectancy','Buffer cache hit ratio','Stolen Server Memory (KB)')
AND object_name LIKE '%Buffer Manager%';
| 指标 | 健康值 |
|---|---|
| Page life expectancy | > 300 秒(持续低于 300 说明内存压力) |
| Buffer cache hit ratio | > 95% |
| Stolen Server Memory | 不应持续增长 |
-- 确认 max server memory 是否设置
SELECT name, value_in_use FROM sys.configurations WHERE name = 'max server memory (MB)';
17.7 tempdb 爆满
SELECT SUM(unallocated_extent_page_count)*8/1024 AS free_mb,
SUM(user_object_reserved_page_count)*8/1024 AS user_obj_mb,
SUM(internal_object_reserved_page_count)*8/1024 AS internal_mb,
SUM(version_store_reserved_page_count)*8/1024 AS version_store_mb
FROM tempdb.sys.dm_db_file_space_usage;
-- 谁在占
SELECT session_id, user_objects_alloc_page_count*8/1024 AS user_mb,
internal_objects_alloc_page_count*8/1024 AS internal_mb
FROM tempdb.sys.dm_db_session_space_usage ORDER BY user_mb DESC;
常见原因:大排序/哈希(worktable)、READ_COMMITTED_SNAPSHOT 的版本存储、长期未提交事务、临时表未释放。
18. 危险命令与避坑清单
| 命令 | 后果 | 防护 |
|---|---|---|
DROP DATABASE |
整库消失 | 权限收紧 + 备份验证 |
TRUNCATE TABLE |
数据清空、不可回滚 | 先 SELECT COUNT(*),重要表先备份 |
DELETE FROM t; |
全表删、日志暴涨 | 事务内确认,分批执行 |
UPDATE t SET c=1; |
全表改 | 先 SELECT 同样条件看行数 |
DBCC SHRINKDATABASE |
碎片、IO 抖动 | 用 SHRINKFILE 且仅必要时 |
DBCC DROPCLEANBUFFERS |
缓存清空、性能雪崩 | 生产禁用 |
DBCC CHECKDB ... REPAIR_ALLOW_DATA_LOSS |
丢数据 | 先复制文件留底,优先从备份恢复 |
KILL <spid> |
回滚大事务可能数小时 | 先看 open tran 年龄 |
ALTER DATABASE ... SET SINGLE_USER WITH ROLLBACK IMMEDIATE |
踢掉所有用户 | 维护窗口执行 |
| 恢复模式从 FULL 改 SIMPLE | 日志链断裂,无法 PITR | 确认可容忍丢数据 |
sp_configure 'max server memory' 设为极大值 |
OS 内存耗尽 | 留 4~8GB 给系统 |
用 sa 跑业务 |
影响面最大 | 业务用专属登录名 + 最小权限 |
18.1 变更前检查清单
-- 1) 确认实例与库
SELECT @@SERVERNAME, DB_NAME(), SERVERPROPERTY('ProductVersion');
-- 2) 备份
BACKUP DATABASE appdb TO DISK='F:\B\pre_change.bak' WITH INIT, COMPRESSION, CHECKSUM;
BACKUP LOG appdb TO DISK='F:\B\pre_change.trn' WITH INIT, COMPRESSION;
-- 3) 看阻塞与长事务
SELECT session_id, blocking_session_id, wait_time FROM sys.dm_exec_requests WHERE blocking_session_id <> 0;
SELECT transaction_id, DATEDIFF(SECOND, transaction_begin_time, GETDATE()) age
FROM sys.dm_tran_active_transactions;
-- 4) 看 AG 延迟
SELECT database_name, log_send_queue_size, redo_queue_size FROM sys.dm_hadr_database_replica_states;
-- 5) 记录基线
SELECT name, compatibility_level, recovery_model_desc FROM sys.databases WHERE name='appdb';
19. 附录:巡检脚本与 DMV 速查
19.1 日常巡检脚本
SET NOCOUNT ON;
PRINT '========== 版本与运行时长 ==========';
SELECT @@SERVERNAME AS server_name, @@VERSION AS version,
sqlserver_start_time, DATEDIFF(HOUR, sqlserver_start_time, GETDATE()) AS uptime_h;
PRINT '========== 数据库状态 ==========';
SELECT name, state_desc, recovery_model_desc, compatibility_level,
log_reuse_wait_desc, is_read_only
FROM sys.databases ORDER BY database_id;
PRINT '========== 数据与日志空间 ==========';
SELECT DB_NAME(database_id) AS db,
SUM(CASE WHEN type_desc='ROWS' THEN size END)*8/1024 AS data_mb,
SUM(CASE WHEN type_desc='LOG' THEN size END)*8/1024 AS log_mb
FROM sys.master_files GROUP BY database_id ORDER BY data_mb DESC;
PRINT '========== 磁盘余量 ==========';
SELECT DISTINCT volume_mount_point, total_bytes/1024/1024/1024 AS total_gb,
available_bytes/1024/1024/1024 AS free_gb,
CAST(available_bytes*100.0/total_bytes AS DECIMAL(5,1)) AS free_pct
FROM sys.master_files CROSS APPLY sys.dm_os_volume_stats(database_id, file_id);
PRINT '========== 连接与请求 ==========';
SELECT COUNT(*) AS sessions FROM sys.dm_exec_sessions WHERE is_user_process = 1;
SELECT session_id, status, command, wait_type, wait_time, blocking_session_id,
DB_NAME(database_id) AS db
FROM sys.dm_exec_requests WHERE session_id > 50 AND session_id <> @@SPID;
PRINT '========== 阻塞 ==========';
SELECT session_id, blocking_session_id, wait_type, wait_time
FROM sys.dm_exec_requests WHERE blocking_session_id <> 0;
PRINT '========== 等待 TOP10 ==========';
SELECT TOP 10 wait_type, wait_time_ms/1000 AS wait_sec, waiting_tasks_count
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN ('SLEEP_TASK','LAZYWRITER_SLEEP','CHECKPOINT_QUEUE',
'XE_TIMER_EVENT','WAITFOR','BROKER_TASK_STOP','SQLTRACE_BUFFER_FLUSH')
ORDER BY wait_time_ms DESC;
PRINT '========== 内存 ==========';
SELECT physical_memory_in_use_kb/1024 AS used_mb,
page_fault_count
FROM sys.dm_os_process_memory;
SELECT value_in_use AS max_server_memory_mb FROM sys.configurations
WHERE name = 'max server memory (MB)';
PRINT '========== 近 3 天备份 ==========';
SELECT database_name, type, backup_finish_date,
backup_size/1024/1024 AS size_mb, compressed_backup_size/1024/1024 AS comp_mb
FROM msdb.dbo.backupset WHERE backup_finish_date > DATEADD(DAY,-3,GETDATE())
ORDER BY backup_finish_date DESC;
PRINT '========== AG 状态 ==========';
SELECT ag.name AS ag_name, ar.replica_server_name, ars.role_desc,
ars.synchronization_health_desc,
drs.database_name, drs.log_send_queue_size, drs.redo_queue_size
FROM sys.availability_groups ag
JOIN sys.availability_replicas ar ON ar.group_id = ag.group_id
JOIN sys.dm_hadr_availability_replica_states ars ON ars.replica_id = ar.replica_id
LEFT JOIN sys.dm_hadr_database_replica_states drs ON drs.replica_id = ar.replica_id;
PRINT '========== 碎片 TOP10 ==========';
SELECT TOP 10 OBJECT_NAME(ips.object_id) AS table_name, i.name AS index_name,
ips.avg_fragmentation_in_percent, ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON i.object_id = ips.object_id AND i.index_id = ips.index_id
WHERE ips.page_count > 1000 AND ips.avg_fragmentation_in_percent > 10
ORDER BY ips.avg_fragmentation_in_percent DESC;
sqlcmd -S localhost -U sa -P "$SA_PWD" -C -b -i health.sql -o health_$(date +%F).txt
19.2 常用系统存储过程
| 命令 | 作用 |
|---|---|
sp_who2 |
会话与阻塞一览 |
sp_helpdb |
数据库信息 |
sp_spaceused |
空间使用 |
sp_help <table> |
表结构 |
sp_helptext <proc> |
存储过程定义 |
sp_lock |
锁(老,建议用 DMV) |
sp_configure |
配置 |
sp_readerrorlog |
读错误日志 |
sp_cycle_errorlog |
轮转错误日志 |
sp_updatestats |
全库更新统计 |
sp_refreshview |
刷新视图元数据 |
sp_change_users_login |
修复孤儿用户 |
sp_query_store_force_plan |
强制计划 |
sp_WhoIsActive(第三方) |
最强的活动会话诊断脚本 |
19.3 关键 DMV 速查
| DMV | 用途 |
|---|---|
sys.dm_exec_requests |
当前请求 |
sys.dm_exec_sessions |
会话 |
sys.dm_exec_connections |
连接与加密状态 |
sys.dm_exec_sql_text |
SQL 文本 |
sys.dm_exec_query_plan |
执行计划 |
sys.dm_exec_query_stats |
查询统计(实例级) |
sys.dm_os_wait_stats |
等待统计 |
sys.dm_os_waiting_tasks |
当前等待任务 |
sys.dm_tran_locks |
锁 |
sys.dm_tran_active_transactions |
活动事务 |
sys.dm_db_index_usage_stats |
索引使用 |
sys.dm_db_index_physical_stats |
索引碎片 |
sys.dm_db_missing_index_details |
缺失索引建议 |
sys.dm_os_volume_stats |
磁盘容量 |
sys.dm_os_process_memory |
进程内存 |
sys.dm_hadr_availability_replica_states |
AG 状态 |
sys.dm_hadr_database_replica_states |
AG 数据库同步 |
sys.query_store_* |
Query Store |
19.4 关键路径与端口
| 项 | 值 |
|---|---|
| 默认端口 | 1433(命名实例动态,SQL Browser 用 UDP 1434) |
| 默认实例 | MSSQLSERVER |
| Windows 数据目录 | C:\Program Files\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQL\DATA |
| Linux 数据目录 | /var/opt/mssql/data |
| Linux 配置 | /var/opt/mssql/mssql.conf |
| Linux 日志 | /var/opt/mssql/log/errorlog |
| 备份默认目录 | 安装时指定,通常 C:\Program Files\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQL\Backup |
附:与工作区其他手册的配合
- 操作系统层见
CentOS-7-10-常规运维指令手册.md/Ubuntu-常用运维指令手册.md - 放行端口:
firewall-cmd --add-port=1433/tcp --permanent(Linux),Windows 用New-NetFirewallRule - Linux 版 SQL Server 依赖
openldap、krb5、openssl,安装前确认系统库版本 - 与其他数据库的核心差异:
GO批处理分隔符、恢复模式决定能否 PITR、max server memory必须手工设上限、DENY优先于GRANT、sysadmin绕过所有权限检查