虚影清理过程是一个单线程后台进程,用于删除已标记为要删除的页面的记录。 以下文章概述了此过程。
幽灵记录
从索引页叶级别被删除的记录不会从页面中物理删除,而是记录会被标记为“待删除”或 成为虚影。 这意味着该行仍保留在页面上,但行标题稍微更改了一下,以指示该行实际上是一个幽灵。 这是为了在删除操作期间优化性能。 幽灵对于行级锁定是必要的,而对于快照隔离也是必要的,因为我们需要维护行的旧版本。
幽灵记录清理任务
标记为删除或 虚影的记录由后台虚影清理过程清除。 提交删除事务后,此后台进程有时会运行,并从页面中实际删除虚影记录。 幽灵清理过程会自动运行,每隔一定时间检查页面是否被标记为幽灵记录(SQL Server 2012+ 每隔 5 秒运行一次,SQL Server 2008/2008R2 每隔 10 秒运行一次)。 如果找到任何记录,则它会执行并删除标记为删除或幽灵化的记录,每次执行最多影响10页。
当记录被虚影化时,数据库将标记为具有虚影条目,而虚影清理过程将仅扫描这些数据库。 在删除所有虚影记录后,虚影清理过程也会将数据库标记为“没有虚影记录”,下次运行时,该数据库将跳过此数据库。 此过程还将跳过它无法打开共享锁的任何数据库,并在下次运行时重试。
下面的查询可以识别单个数据库中存在多少条虚影记录。
SELECT sum(ghost_record_count) total_ghost_records, db_name(database_id)
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, 'SAMPLED')
group by database_id
order by total_ghost_records desc
禁用幽灵清理
在具有许多删除操作的高负载系统上,虚影清理过程可能会导致性能问题,因为它保持页面在缓冲池中并产生 IO 操作。 因此,可以使用 跟踪标志 661 禁用此过程。 但是,禁用进程会产生性能影响。
禁用虚影清理过程可能会导致数据库变得不必要的大,并可能导致性能问题。 由于虚影清理进程会删除标记为虚影的记录,因此禁用该过程会将这些记录保留在页面上,从而阻止 SQL Server 重用此空间。 这会强制 SQL Server 将数据添加到新页面,从而导致数据库文件膨胀,也可能导致 页面拆分。 页面拆分会导致创建执行计划以及执行扫描作时出现性能问题。
一旦禁用虚影清理过程,需要采取一些措施来删除虚影记录。 一个选项是执行索引重新生成,这将在页面上移动数据。 另一个选项是手动运行 sp_clean_db_free_space (清理所有数据库数据文件)或 sp_clean_db_file_free_space (清理单个数据库数据文件),这将删除虚影记录。
警告
通常不建议禁用幽灵清理进程。 在生产环境中永久实施之前,应在受控环境中对这样做进行彻底测试。