恢复数据库是否清除缓冲区缓存和存储的 proc 缓存

Joy*_*ker 8 sql-server

在我们的开发服务器上,我们每周刷新数据库(从生产备份中恢复)。我的问题是 restore db 是否从 sql 内存中清除其缓冲区缓存/存储过程缓存?它是否与DBCC FREEPROCCACHE和具有相同/相似的效果 DBCC DROPCLEANBUFFERS

谢谢。

Mar*_*ith 13

是的。还原前与数据库关联的缓冲区和计划缓存与还原后的数据库无关,因此将被清除。就所有意图和目的而言,恢复的数据库是一个完全独立的、不相关的实体。缓存中没有任何东西可以重用。


swa*_*eck 12

有趣的问题(现在我看到@MarkStorey-Smith 已经回答了我犹豫不决 - 所以接受他,因为他先回答了)我决定做一些检查。我有一个以analysis我的本地虚拟机之一命名的数据库。所以我运行了这个脚本(关于缓冲区的更多信息和我的查询基础可以在这里找到):

SELECT database_id 
    FROM sys.databases
    WHERE name = 'analysis';
GO
-- database_id = 7


            DECLARE @total_buffer INT;
            SELECT  @total_buffer = cntr_value
                FROM sys.dm_os_performance_counters
                WHERE RTRIM([object_name]) LIKE '%Buffer Manager'
                    AND (counter_name = 'Total Pages' --this is 2008
                    OR counter_name = 'Database pages'); -- this is 2012
            ;WITH src AS (
                SELECT
                    database_id, DB_Buffer_Pages = COUNT_BIG(*)
                    FROM sys.dm_os_buffer_descriptors
                    --WHERE database_id BETWEEN 5 AND 32766
                    GROUP BY database_id
                )

            SELECT 
                @@SERVERNAME AS InstanceName,
                GETDATE() AS collection_date,
                database_name = DB_NAME(mem.database_id), 
                db_buffer_pages, 
                cached_size_mb,
                db_buffer_pct, 
                cpu_time, 
                cpu_percent_usage, 
                total_io_mb, 
                io_percent          
            FROM (              
                    SELECT
                    database_id,
                    db_buffer_pages = DB_Buffer_Pages,
                    cached_size_mb = DB_Buffer_Pages / 128.0,
                    db_buffer_pct = CONVERT(DECIMAL(6,3),
                                        DB_Buffer_Pages * 100.0 / @total_buffer)        
                    FROM src
                ) mem
                JOIN (
                        SELECT 
                            database_id, cpu_time, 
                            CAST(cpu_time * 1.0 / SUM(cpu_time) OVER() * 100.0 AS DECIMAL(5, 2)) AS cpu_percent_usage
                        FROM (
                                SELECT database_id, SUM(total_worker_time) AS cpu_time
                                FROM sys.dm_exec_query_stats AS qs
                                CROSS APPLY (SELECT CONVERT(int, value) AS database_id 
                                                FROM sys.dm_exec_plan_attributes(qs.plan_handle)
                                                WHERE attribute = N'dbid') AS F_DB
                                GROUP BY database_id) DB_CPU_Stats
                ) cpu
                    ON mem.database_id = cpu.database_id
                JOIN (
                        SELECT database_id, io_in_mb AS [total_io_mb],
                            CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [io_percent]
                        FROM (
                                SELECT database_id,
                                    CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb
                                FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]
                                GROUP BY database_id) Aggregate_IO_Statistics) [io]
                ON mem.database_id = [io].database_id             
            where mem.database_id = 7
GO  


-- 471

USE master
GO

BACKUP DATABASE analysis TO DISK=N'analysis.bak';
GO
BACKUP LOG analysis TO DISK=N'analysis.trn' WITH NORECOVERY;
GO
RESTORE DATABASE analysis FROM DISK=N'analysis.bak' WITH NORECOVERY;
GO
RESTORE DATABASE analysis FROM DISK=N'analysis.trn';
GO


            DECLARE @total_buffer INT;
            SELECT  @total_buffer = cntr_value
                FROM sys.dm_os_performance_counters
                WHERE RTRIM([object_name]) LIKE '%Buffer Manager'
                    AND (counter_name = 'Total Pages' --this is 2008
                    OR counter_name = 'Database pages'); -- this is 2012
            ;WITH src AS (
                SELECT
                    database_id, DB_Buffer_Pages = COUNT_BIG(*)
                    FROM sys.dm_os_buffer_descriptors
                    --WHERE database_id BETWEEN 5 AND 32766
                    GROUP BY database_id
                )

            SELECT 
                @@SERVERNAME AS InstanceName,
                GETDATE() AS collection_date,
                database_name = DB_NAME(mem.database_id), 
                db_buffer_pages, 
                cached_size_mb,
                db_buffer_pct, 
                cpu_time, 
                cpu_percent_usage, 
                total_io_mb, 
                io_percent          
            FROM (              
                    SELECT
                    database_id,
                    db_buffer_pages = DB_Buffer_Pages,
                    cached_size_mb = DB_Buffer_Pages / 128.0,
                    db_buffer_pct = CONVERT(DECIMAL(6,3),
                                        DB_Buffer_Pages * 100.0 / @total_buffer)        
                    FROM src
                ) mem
                JOIN (
                        SELECT 
                            database_id, cpu_time, 
                            CAST(cpu_time * 1.0 / SUM(cpu_time) OVER() * 100.0 AS DECIMAL(5, 2)) AS cpu_percent_usage
                        FROM (
                                SELECT database_id, SUM(total_worker_time) AS cpu_time
                                FROM sys.dm_exec_query_stats AS qs
                                CROSS APPLY (SELECT CONVERT(int, value) AS database_id 
                                                FROM sys.dm_exec_plan_attributes(qs.plan_handle)
                                                WHERE attribute = N'dbid') AS F_DB
                                GROUP BY database_id) DB_CPU_Stats
                ) cpu
                    ON mem.database_id = cpu.database_id
                JOIN (
                        SELECT database_id, io_in_mb AS [total_io_mb],
                            CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [io_percent]
                        FROM (
                                SELECT database_id,
                                    CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb
                                FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]
                                GROUP BY database_id) Aggregate_IO_Statistics) [io]
                ON mem.database_id = [io].database_id             
            where mem.database_id = 7

--242
Run Code Online (Sandbox Code Playgroud)

恢复前 471 个缓冲页,恢复后 242 个。不幸的是,我没有聚合缓存中的页面类型,但我敢说缓存中的页面与我运行缓冲区分析查询有关。

以下是对 ... 的恢复前和恢复后分析的查询结果analysis

上一页: 在此处输入图片说明

邮政: 在此处输入图片说明


Mik*_*lsh 9

就像 Swasheck 和 Mark 一样,我在这个出来的时候就开始玩了。请不要接受这个答案,接受马克的,实际上甚至不要给我积分,当我看到 Swasheck 发布我开始工作的内容时,我没有截图,但是评论太长了。

所以简短的回答是:是的,你很好

也就是说,我听说过过去版本的 SQL 中的报告,人们似乎认为这是必需的。所以我想确定一下,我做了一个测试。我创建了一个数据库,创建了一些表,然后使用 Glenn 的查询来查看在恢复之前该数据库中有多少在缓冲区缓存中。在我有大约 50.2MB 的数据之前,在我有大约 1.5MB 之后 - 这很可能是因为恢复后的某些事情,而不是因为数据挂起。

我之前还运行了几个查询,并包含了诸如“foo”之类的表别名,因此我可以使用下面的查询在缓存中找到它们。我看到他们都在那里,做了恢复,他们走了。

SELECT st.text, qs. sql_handle, qs.plan_handle
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) st
where text like '%foo%'
Run Code Online (Sandbox Code Playgroud)

所以我可以肯定地说,在我对 SQL Server 2012 的有限测试中,数据库的痕迹完全从缓冲池和计划缓存中消失了。这是有道理的,因为它们相关的数据库消失了,这是预期的行为。

也就是说 - 在恢复之后,您绝对应该考虑做的一件事是更新您的统计数据。我喜欢从干净的统计数据开始,我真的很喜欢看到人们在开发中使用生产数据,我喜欢从干净的统计数据开始。在开发中使用真实数据真是太好了。(警告 - 有时您需要在执行此操作之前对数据进行去标识化,但要使用真实数据分布和大小进行测试。)