SQL Server 的内存管理是一个庞大的主题,涉及特别多的概念和技术,例如常见的 Plan Cache、Buffer Pool、Memory Clerks 等。本文仅是管中窥豹,描述常见的内存管理相关概念。

在了解内存管理之前,通过 sys.dm_os_memory_clerks 视图可以查询内存的使用职责(Memory Clerks),也就是内存的消耗者。

SELECT [type], SUM(pages_kb) AS total_pages_kb
FROM sys.dm_os_memory_clerks
WHERE pages_kb != 0
GROUP BY [type]
ORDER BY total_pages_kb DESC;

SQL Server 中最主要的内存组件就是缓冲池(Buffer Pool, or Bpool)。缓冲池是一个 8KB 页面的集合,任何大于 8KB 的内存块都需要进行单独分配管理,例如 COM Objects、CLR Code、Extended Stored Procedures、Large Cached Plan 等。

缓冲区管理器(Buffer Manager)负责从磁盘上的数据文件中读取数据页(Data Page)和索引页(Index Page),将页数据放入 Buffer Pool 中作为数据缓存(Data Cache)。Buffer 指的是内存中的一个 Page,该 Page 的大小与数据页或索引页相同。

SQL Server 采用预读机制(Read-ahead)从磁盘中读取数据页和索引页至缓冲区中,以提高性能。预读机制完全有系统内部控制,不需要进行任何配置和调整。

数据缓存(Data Cache)

数据缓存(Data Cache)中使用哈希(Hashing)方式存储页数据。比如给定 DatabaseID-FileNumber-PageNumber 标识符,通过哈希函数将标识符存放到哈希表中。这样,通过哈希表(Hash Table)提供的快速检索功能,数据库引擎仅需要较少的内存读取就可以判断目标页是否存在于缓存中,如果不存在再从磁盘中读入缓存。

SQL Server 会将那些一段时间未被引用的页面缓冲位置标记为空闲页,通过空闲页链表进行管理。当需要新的缓冲页时,将从链表头获取要使用的页地址。

每个数据缓存的页中都包含一块表头区域,包含该页最后两次被引用的相关信息和状态信息,例如描述该页是否为脏页(Dirty Page)。脏页(Dirty Page)指的是从磁盘读取后的数据页被修改过。引用信息则用于实现数据缓存页的页面替换策略,它使用 LRU-K 算法。LRU-K 算法将有价值的缓冲区持有页保留在活跃缓冲池中,而如果缓冲区持有页的引用频率不高,则这些缓冲区页将被逐渐地释放回空闲缓冲区列表中。

LazyWriter 线程

SQL Server 为每个 NUMA 节点都创建了一个 LazyWriter 线程,用于扫描与该节点关联的缓冲区。LazyWriter 线程会进行周期性的睡眠和唤醒,当唤醒时将检查空闲缓冲区列表的长度,如果低于某个阈值,将扫描整个缓冲区。在扫描过程中,当发现页的引用率较低时,将检查脏页指示符。如果该页是脏页,则执行磁盘写入操作。然后该页将被释放回空闲缓冲区列表中。

SQL Server 动态使用内存时,必须不断地侦听可用内存的数量,并且追踪和监视内存的更改,以判断何时增加或减少自身的总内存量。每当 SQL Server 中的内存增加或减少 1MB,或达到服务器内存的 5% 时,将会产生事件通知。

检查点(Checkpoint)

检查点(Checkpoint)线程也定期扫描缓冲区,并将脏数据页写入磁盘。检查点与 LazyWriter 的区别在于,检查点不会向空闲缓冲区列表添加空闲缓冲区。检查点的唯一目的就是,确保将某一时刻前的页面都写入磁盘中,以便始终保持内存中的脏页数量最小。

SQL Server 将检查点的运行过程记录到事务日志中,当 SQL Server 出现故障时,由于已写入了某一时刻前的数据,可以减少恢复时间。

触发检查点的情况有:

  • 手动触发 CHECKPOINT 命令在指定数据库上执行检查点。
  • 日志正在变慢,超过容量的 70%。触发检查点可以截断日志并释放日志空间。
  • 预计需要较长的恢复时间。预计恢复时间比设置的 "Recovery Interval" 选项的值要长时。如果 "Recovery Interval" 设置为 1,意味着检查点每分钟一次。默认值为 0,意味着 SQL Server 将选择合适的值,通常也是 1 分钟。
  • 请求正常关闭 SQL Server,并且不使用 NOWAIT 选项。

检查点线程采用非顺序的方式对缓冲区进行扫描。当找到一个脏页时,会检查该脏页在磁盘上相邻的页面是否也是脏页,以便组合进行 gather-write 大块数据写入,提高性能。

计划缓存(Plan Cache)

在 Buffer Pool 的缓冲区的使用组件中,除了数据缓存(Data Cache),另一个使用量最大的就是对过程与查询计划的缓存,也就是通常说的计划缓存(Plan Cache)

SQL Server 为处数据缓存外所有其他的缓存机制提供通用缓存框架,包括储存方式和资源监视器。储存方式包括三种:

  1. Cache Store:计划缓存(Plan Cache)和行集(Rowset Clerk)为常见的 Cache Store。
  2. User Store:元数据缓存(Metadata Clerk)即为一种 User Store。
  3. Object Store/Memory Pool:SNI Pooling Network Buffer 即为一种 Object Store。

Cache Store 和 User Store 采用 LRU 机制来分配和释放空间,使用 Clock 页面置换算法来实现。而 Object Store 则只是大块的内存,不需要 LRU 机制。

Cache Store 使用哈希表来加快查询速度,而 User Store 则未使用哈希表,Object Store 也未使用哈希表。

通过查看 sys.dm_os_memory_cache_clock_hands 视图,尤其是 removed_last_round_count 列,如果该值在急剧增加,那么是出现内存压力的显著征兆。

SELECT cache_address
,[name]
,[type]
,clock_hand
,clock_status
,removed_last_round_count
FROM sys.dm_os_memory_cache_clock_hands;

Memory Broker

在 SQL Server 中有大量的组件需要使用内存,为了确保每个组件都在有效的使用内存,SQL Server 使用 Memory Broker 分析与内存消耗相关的行为,并改善动态内存分配。

Memory Broker 可以在 Buffer Pool、Query Executor、Query Optimizer 等各种使用缓存的组件间调度内存分配。通过监视内存的需求与消耗,通过带有反馈和改进机制的动态分配算法,协调各组件间形成最佳的内存分配方式。

SELECT *
FROM sys.dm_os_ring_buffers
WHERE ring_buffer_type = 'RING_BUFFER_MEMORY_BROKER';

观察内存

  • sys.dm_os_memory_clerks 该视图描述 SQL Server 实例中正在使用内存的组件职责。
  • sys.dm_os_memory_objects 该视图描述 SQL Server 当前分配的内存对象。
  • sys.dm_os_memory_nodes 该视图描述分配的 NUMA Node 相关信息。
  • sys.dm_os_memory_pools 该视图显示 Object Store 相关信息。
  • sys.dm_os_memory_cache_counters 该视图描述 Cache Store 和 User Store 的运行情况快照。
  • sys.dm_os_memory_cache_hash_tables 该视图描述活跃的缓存信息。
  • sys.dm_os_memory_cache_clock_hands 该视图描述 Clock 页面置换算法的相关信息。

《人人都是 DBA》系列文章索引:

 序号 

 名称 

1

人人都是 DBA(I)SQL Server 体系结构

2

人人都是 DBA(II)SQL Server 元数据

3

人人都是 DBA(III)SQL Server 调度器

4

人人都是 DBA(IV)SQL Server 内存管理

5

人人都是 DBA(V)SQL Server 数据库文件

6

人人都是 DBA(VI)SQL Server 事务日志

7

人人都是 DBA(VII)B 树和 B+ 树

8

人人都是 DBA(VIII)SQL Server 页存储结构

9

人人都是 DBA(IX)服务器信息收集脚本汇编

10

人人都是 DBA(X)资源信息收集脚本汇编

11

人人都是 DBA(XI)I/O 信息收集脚本汇编

12

人人都是 DBA(XII)查询信息收集脚本汇编

13

人人都是 DBA(XIII)索引信息收集脚本汇编

14

人人都是 DBA(XIV)存储过程信息收集脚本汇编

15

人人都是 DBA(XV)锁信息收集脚本汇编

本系列文章《人人都是 DBA》由 Dennis Gao 发表自博客园个人技术博客,未经作者本人同意禁止任何形式的转载,任何自动或人为的爬虫转载或抄袭行为均为耍流氓。

人人都是 DBA(IV)SQL Server 内存管理的更多相关文章

  1. SQL Server 内存管理

    windows memory:  Memory: Cache Bytes 是系统的working set, 也就是系统使用的物理内存数目. 可以观察Windows用了多少物理内存. 1. System ...

  2. SQL Server 内存管理在64位时代的改变

    64位机上  地址空间比以前大了去了.它引起的改变多了去了 1.MemToLeave这个词不存在了.因为SQL Server以不再做这种预留空间的事了,也就是说multiple page 想用多少就用 ...

  3. 人人都是 DBA(VIII)SQL Server 页存储结构

    当在 SQL Server 数据库中创建一张表时,会在多张系统基础表中插入所创建表的信息,用于管理该表.通过目录视图 sys.tables, sys.columns, sys.indexes 可以查看 ...

  4. 人人都是 DBA(VI)SQL Server 事务日志

    SQL Server 的数据库引擎通过事务服务(Transaction Services)提供事务的 ACID 属性支持.ACID 属性包括: 原子性(Atomicity) 一致性(Consisten ...

  5. 人人都是 DBA(V)SQL Server 数据库文件

    SQL Server 数据库安装后会包含 4 个默认系统数据库:master, model, msdb, tempdb. SELECT [name] ,database_id ,suser_sname ...

  6. 人人都是 DBA(III)SQL Server 调度器

    在 SQL Server 中,当数据库启动后,SQL Server 会为每个物理 CPU(包括 Physical CPU 和 Hyperthreaded)创建一个对应的任务调度器(Scheduler) ...

  7. 人人都是 DBA(II)SQL Server 元数据

    SQL Server 中维护了一组表用于存储 SQL Server 中所有的对象.数据类型.约束条件.配置选项.可用资源等信息,这些信息称为元数据信息(Metadata),而这些表称为系统基础表(Sy ...

  8. 人人都是 DBA(I)SQL Server 体系结构

    在了解 SQL Server 数据库时,可以先从数据库的体系结构来观察.SQL Server 的体系结构中包含 4 个主要组成部分: 协议层(Protocols) 关系引擎(Relational En ...

  9. 人人都是 DBA(XII)查询信息收集脚本汇编

    什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...

随机推荐

  1. [11]APUE:(文件)记录锁

    [a] 概念 建议锁:在遵循相同记录锁规则的进程间生效,通常用于保证某个程序自身多个进程间的数据一致性 强制锁:意在保证所有进程间的数据一致性,但不一定有效:如不能应对先 unlink 后建立同名副本 ...

  2. spring mvc 工作流程

    Spring Web MVC 处理Http请求的大致过程:一旦Http请求到来,DispatcherSevlet将负责将请求分发.DispatcherServlet可以认为是Spring提供的前端控制 ...

  3. 关于Linux的 /sbin权限问题

    安装ubuntu一段时间后新增了用户,突然发现原来的用户用不了 ifconfig ,提示找不到命令 一试之下发现/sbin/ifconfig,可以,明白了是因为用户新增了,系统不认为当前用户是唯一用户 ...

  4. GDI+ 发生一般性错误解决办法

    错误的代码g对象继续占用 未释放资源 如果路径不一样 没问题 相同路径 获取图片进行 缩略会造成GDI错误 /// <summary> /// 生成缩略图 /// </summary ...

  5. Hadoop2.6.0的FileInputFormat的任务切分原理分析(即如何控制FileInputFormat的map任务数量)

    前言 首先确保已经搭建好Hadoop集群环境,可以参考<Linux下Hadoop集群环境的搭建>一文的内容.我在测试mapreduce任务时,发现相比于使用Job.setNumReduce ...

  6. 【Java】JavaWeb权限管理

    权限管理分析 每个网站都涉及到访问权限的控制.每个站点资源都需要被管理起来,用户只有具有访问某个资源的特定权限,才能够访问,否则拒绝访问.网站的访问权限控制,一种方法从 URI 入手,站点的每个资源都 ...

  7. HTML5+CSS3学习笔记(二) 页面布局:HTML5新元素及其特性

    HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面布局,加上CSS3的效果渲染,快速建立丰富灵活的web页面显得非常简单. 本次学习HTML5的新标签元素有: <head ...

  8. Linux系统目录结构

    Linux系统目录结构图 目录:/ 是Linux的根目录 每个文件和目录从根目录开始,只有root用户具有该目录下的写权限: /root是root用户的主目录,这与 / 目录不一样: 目录:/bin ...

  9. 1032: [JSOI2007]祖码Zuma

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1032 Description 这是一个流行在Jsoi的游戏,名称为祖玛.精致细腻的背景,外加神 ...

  10. python 跨模块实现按照文件大小,日期实现日志分割,反转

    笔者的一个自动化测试平台项目,采用了python作为后端服务器语言.项目基于快速成型目的,写了一个极其简陋的日志记录功能,支持日志记录到文件和支持根据日志级别在终端打印不同颜色的log.但随着测试平台 ...