01_SQLServer 体系架构全解 ------ 实例进程、关系引擎、SQLOS 与事务日志深入
系列定位 :《SQL Server 数据库全栈运维实战系列》第 01 篇,与《MySQL 数据库全栈运维实战系列》同构对标(对标 MySQL 01 对应篇目)。适用版本 :SQL Server 2019/2022(2017 及以下差异随文标注)。官方文档:Microsoft Learn SQL Server 2019/2022 文档、数据库引擎体系结构(Database Engine Architecture)章节。
一、SQL Server 总体架构(一张图看懂)
SQL Server 是一个单进程多线程的 RDBMS:整个实例只有一个主进程 sqlservr.exe,所有连接、查询、缓冲、日志、锁都在这个进程内部完成,由一层自研的 SQLOS(SQL 操作系统)做线程调度与内存管理。这与 MySQL「一个 mysqld 进程 + 插件式存储引擎」的思路类似,但 SQL Server 的引擎层是内建的,不可插拔。

图 1
| 层 | 职责 | 类比 MySQL |
|---|---|---|
| 协议层 | TDS 端点监听、登录认证、连接上下文 | 连接层与通信协议 |
| 关系引擎 | 词法语法解析、Algebrizer 绑定、优化器选计划、任务执行 | MySQL 的 SQL 层(解析器加优化器加执行器) |
| 存储引擎 | 缓冲池、数据页读写、事务日志、锁与闩 | InnoDB 引擎内部 |
| SQLOS | 线程调度器、工作线程池、内存节点、死锁检测 | 没有直接对应,MySQL 依赖 OS 线程 |
| 文件层 | mdf 数据文件、ldf 日志文件、tempdb | ibd 加 redo 加 binlog |
核心差异:MySQL 的存储引擎是可插拔的,同实例可混用 InnoDB 与 MyISAM;SQL Server 只有一个内建引擎,所有数据库共享同一套缓冲池与日志机制,换「引擎」本质上只能靠架构手段(列存储、内存优化表)补足。
二、协议层与连接管理
客户端(SSMS、JDBC、ODBC、应用程序)通过 TDS(Tabular Data Stream)协议连接实例。SQL Server 监听两类入口:默认实例 TCP 1433,命名实例由 SQL Browser 服务(UDP 1434)动态分配端口后告知客户端。

图 2
-- 查看当前会话(解释:DBA 第一视图,等价于 MySQL 的 SHOW PROCESSLIST)
SELECT session_id, login_name, host_name, program_name, status, cpu_time, logical_reads
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;
-- 查看底层物理连接
SELECT session_id, net_transport, protocol_type, auth_scheme, local_tcp_port
FROM sys.dm_exec_connections
WHERE session_id > 50;
-- 查看调度器负载(解释:每个 CPU 核对应一个调度器)
SELECT scheduler_id, cpu_id, current_tasks_count, runnable_tasks_count, work_queue_count
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255;
| 要点 | 说明 |
|---|---|
| 认证模式 | Windows 集成认证,或混合模式(SQL 账号即 sa 类登录名) |
| 连接上限 | 理论无硬限制,受 max worker threads 控制(默认 0 即按核数自动配置) |
| 连接池 | 应用侧建议 ADO.NET 连接池,减少 TDS 握手开销 |
| 中断会话 | KILL 53(按 session_id 杀会话),对应 MySQL 的 KILL QUERY 与 KILL 线程 |
三、关系引擎:解析 → 绑定 → 优化 → 执行
一条 T-SQL 进入实例后,关系引擎(Query Processor)依次做四件事:解析器(Parser)做词法语法分析生成分析树;Algebrizer 把树中的表名列名绑定到元数据并确定数据类型;查询优化器(Query Optimizer)基于开销模型在几十种候选计划中选一个;执行器(Query Execution Engine)按计划算子逐层取数并把结果以 TDS 流回客户端。

图 3
-- 查看执行计划的两种姿势(解释:对应 MySQL 的 EXPLAIN)
SET SHOWPLAN_XML ON; -- 只输出计划不执行语句
GO
SELECT * FROM sales.OrderHeader WHERE OrderID = 10248;
GO
SET SHOWPLAN_XML OFF;
GO
-- 实际执行并统计 IO 与耗时
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT * FROM sales.OrderHeader WHERE OrderID = 10248;
| 组件 | 职责 | 调优入口 |
|---|---|---|
| Parser | 语法树构建 | T-SQL 语法正确性 |
| Algebrizer | 对象绑定、类型推导 | 隐式类型转换隐患 |
| 优化器 | 基数估算、索引选择、连接顺序 | 执行计划、统计信息、Query Store |
| 执行器 | 按计划算子执行 | 实际行数与估算行偏差 |
四、SQLOS:线程调度与内存管理(官方:SQL Server Operating System)
SQLOS 是实例内部的迷你操作系统,向下对 Windows 隐藏差异,向上给关系引擎提供调度与内存服务。它按物理 NUMA 节点把 CPU 划成多个调度器(Scheduler),每个调度器同一时刻只让一个工作线程(Worker)在 CPU 上运行,任务(Task)在可运行队列里排队等待------这是 SQL Server 高并发下不被 OS 线程风暴压垮的关键。

图 4
| SQLOS 对象 | 说明 | 类比 MySQL |
|---|---|---|
| Scheduler | 每 CPU 核一个调度器,MAXDOP 控制并行度上限 | 无线程池,靠 OS |
| Worker | 工作线程,池化复用 | MySQL 每连接一线程 |
| Memory Node | 按 NUMA 节点管理内存 | 没有显式对应 |
| Deadlock Monitor | 定期探测锁等待环,牺牲代价小的事务 | InnoDB 锁监控线程 |
-- 内存总貌(解释:看缓冲池吃了多少内存)
SELECT physical_memory_in_use_kb, locked_page_allocations_kb,
available_commit_limit_kb
FROM sys.dm_os_process_memory;
-- 调度器可运行队列是否堆积(解释:runnable 长期大于 0 说明 CPU 打满)
SELECT scheduler_id, current_tasks_count, runnable_tasks_count
FROM sys.dm_os_schedulers WHERE scheduler_id < 255;
五、缓冲池与数据页:内存与磁盘结构
SQL Server 的数据以 8KB 页为最小单位,读盘必须整页读入缓冲池(Buffer Pool)的内存页;所有读写先在内存页上完成,再由 Checkpoint 与 LazyWriter 按策略刷回数据文件。一条改动要落盘前,先写事务日志(预写日志 WAL),崩溃后靠日志前滚恢复。
| 内存与磁盘组件 | 职责 | 类比 MySQL |
|---|---|---|
| Buffer Pool | 8KB 数据页缓存,实例最大的一块内存 | InnoDB Buffer Pool |
| Plan Cache | 执行计划缓存,按批处理文本哈希复用 | 没有 query cache 的 8.0 时代靠 prepared 语句 |
| Checkpoint | 把脏页批量刷盘,推进日志最小恢复点 | InnoDB Checkpoint |
| LazyWriter | 内存紧张时按策略淘汰旧页 | InnoDB LRU 后台刷页 |
| 事务日志 .ldf | WAL 前滚恢复,日志备份的载体 | redo log |
| 数据文件 .mdf | 数据与索引物理存储 | ibd 表空间文件 |
-- 缓冲池命中率(解释:应长期大于 99%)
SELECT (a.cntr_value * 1.0 / b.cntr_value) * 100.0 AS BufferCacheHitRatio
FROM sys.dm_os_performance_counters a
JOIN sys.dm_os_performance_counters b
ON b.counter_name = 'Buffer cache hit ratio base'
WHERE a.counter_name = 'Buffer cache hit ratio';
-- 谁占了缓冲池大头(解释:按库统计缓存页数)
SELECT DB_NAME(database_id) AS db_name, COUNT(*) AS cached_pages
FROM sys.dm_os_buffer_descriptors
WHERE database_id > 4
GROUP BY database_id ORDER BY cached_pages DESC;
六、事务日志与恢复模型(官方:The Transaction Log)
每个数据库至少一个 .ldf 文件,内部被切成多个虚拟日志文件(VLF)。所有修改先写日志缓冲再刷 ldf,数据页晚写,这就是 WAL。恢复模型决定日志的命运:简单模式日志可被截断复用,完整模式日志持续增长直到日志备份截断,大容量日志模式是完整模式的批量操作变体。
| 恢复模型 | 日志行为 | 类比 MySQL |
|---|---|---|
| SIMPLE | 日志自动截断,不能日志备份 | 不开 binlog,靠 redo 崩溃恢复 |
| FULL | 日志完整保留直到日志备份,支持时点恢复 | binlog 常开加 ROW 格式 |
| BULK_LOGGED | 批量操作最小日志记录,仍可日志备份 | 批量写场景的折中 |
-- 查看与切换恢复模型
SELECT name, recovery_model_desc FROM sys.databases;
ALTER DATABASE OrderDB SET RECOVERY FULL; -- 解释:生产库必须完整模式
GO
-- 查看日志文件的 VLF 概况(解释:VLF 太多会拖慢恢复与日志重做)
DBCC LOGINFO(N'OrderDB');
七、一条 T-SQL 的生命周期(全链路)

图 5
八、锁与隔离级别
SQL Server 用锁保护并发一致性:行级共享锁 S、排他锁 X、更新锁 U、表级意向锁 IS/IX,架构修改用 Sch-S 与 Sch-M。隔离级别从低到高为未提交读、提交读(默认)、可重复读、可串行化,外加两个基于行版本控制的快照级别(SNAPSHOT 与 RCSI),行版本存在 tempdb 中,对应 MySQL 的 MVCC。
| 机制 | 说明 | 类比 MySQL |
|---|---|---|
| 行锁 | 键范围锁防幻读,粒度可到行 | InnoDB 记录锁加间隙锁 |
| 意向锁 | 表级 IS/IX 与行锁协同 | InnoDB 意向锁 |
| 快照隔离 | tempdb 行版本,读不加锁 | InnoDB MVCC 一致性读 |
| 死锁检测 | Lock Monitor 秒级探测并回滚牺牲者 | InnoDB 死锁检测 |
-- 查看当前阻塞关系(解释:blocking_session_id 就是元凶)
SELECT session_id, blocking_session_id, wait_type, wait_time
FROM sys.dm_exec_requests
WHERE blocking_session_id <> 0;
九、系统数据库与 tempdb 速览
实例装完自带五个系统数据库:master 记录实例级元数据,model 是新建库的模板,msdb 存 SQL Server Agent 作业与备份历史,tempdb 是全局临时库(临时表、行版本、表变量都住这),resource 是只读的系统对象定义库。2019 起安装程序会按逻辑 CPU 核数自动把 tempdb 配成多个数据文件,减少 tempdb 分配争用。
-- 查看全部系统库与状态
SELECT name, database_id, recovery_model_desc, state_desc
FROM sys.databases ORDER BY database_id;
十、2019/2022 新特性速览(官方:What's New in SQL Server)
| 特性 | 说明 |
|---|---|
| 智能查询处理 IQP(2019) | 批量自适应内存反馈、标量 UDF 内联、近似 COUNT DISTINCT,免改代码提速 |
| tempdb 默认多文件 | 安装时按核数自动配置,默认数据文件与自动增长更合理 |
| 数据分类与发现 | 列级敏感度标签,配合审计 |
| 参数敏感计划优化(2022) | 同一存储过程对不同参数复用坏计划的顽疾由引擎自动处理 |
| Query Store 增强(2022) | 可读副本上启用 Query Store,自动策略可强制计划 |
| 账本数据库 Ledger(2022) | 防篡改、可验证数据历史 |
| MAXDOP 默认建议(2022) | 安装期按硬件自动给出并行度建议 |
-- 验证当前版本(解释:区分 2019 与 2022 的第一手命令)
SELECT @@VERSION AS version;
-- 期望返回含 Microsoft SQL Server 2019 (RTM-CU...) 或 2022 (RTM-CU...) 的文本
十一、要点速记
- 单实例单进程:sqlservr.exe 一个进程承载所有数据库,SQLOS 在内部做调度与内存。
- 四大组件:协议层、关系引擎、存储引擎、SQLOS,与 MySQL 三层结构对照理解最快。
- WAL 铁律:先写日志后写数据,崩溃靠 .ldf 前滚恢复。
- 缓冲池是性能核心:max server memory 决定它能吃多少内存,命中率应长期大于 99%。
- DMV 是运维入口:sys.dm_exec_sessions、sys.dm_os_schedulers、sys.dm_os_buffer_descriptors 对应 MySQL 的 processlist 与 performance_schema。
十二、踩坑记录(实测汇总)
| # | 坑 | 现象 | 解决 |
|---|---|---|---|
| 1 | 忘记设 max server memory | 实例吃光 OS 内存,Windows 开始抖动 | sp_configure 限制实例内存为物理内存减 4GB 以上余量 |
| 2 | tempdb 只有一个文件 | 批量插入出现 PFS 页争用、等待 GAM 页 | 按逻辑核数加 tempdb 数据文件,自动增长设为一致 |
| 3 | 恢复模型停在 SIMPLE | 想做日志备份时报操作不允许 | 生产库改 FULL 后先做一次完整备份,日志才开始可备份 |
| 4 | KILL 了大事务却不退 | 会话长时间 ROLLBACK 状态无进展 | 等待回滚完成,勿重启实例,重启只会再次前滚回滚 |
| 5 | 用旧版 SSMS 连 2022 | 某些菜单功能缺失或报错 | 升级 SSMS 到 19 以上,SSMS 与引擎版本解耦 |
| 6 | 误以为 LIKE 走索引 | 执行计划全表扫描 | 前缀匹配才有 SARG,中间通配符只能扫描 |
| 7 | 计划缓存被一次性查询冲垮 | 大报表偶尔全量编译导致其他会话卡顿 | 对大报表查询加 OPTION (RECOMPILE) 或 Query Store 固定计划 |
十三、参考资料(官方正式文档)
本文章属于《SQL Server 数据库全栈运维实战系列》基础与架构篇。欢迎收藏、交流。