假设数据库使用完全恢复模型,那么在SQL Server中(通过INSERT
/ UPDATE
etc)写入记录时,预先写入日志将确保在修改数据页之前将更改写入日志文件。
日志和数据页条目均在RAM中进行,然后由Checkpoint提交到磁盘。
如果发生系统崩溃(出于参数争用而断电),脏页(在RAM中更改但未提交到磁盘的IE数据)会发生什么情况,因为RAM的内容在系统重新启动后无法生存,是否会丢失数据? ?
编辑
经过一些测试,我可以看到脏页没有丢失,但是我不确定为什么:
使用本教程
创建一个测试数据库
CREATE DATABASE DirtyPagesDB
GO
USE DirtyPagesDB
GO
关闭自动检查点
DBCC TRACEON(3505, -1);
DBCC TRACESTATUS();
创建一个表,插入一些数据并发出一个检查点:
CREATE TABLE t1 (Speaker_Bio CHAR(8000))
GO
INSERT INTO t1 VALUES ('SQL'),('Authority')
GO
CHECKPOINT
确认没有脏页
-- Get the rows of dirtied pages
SELECT
database_name = d.name,
OBJECT_NAME =
CASE au.TYPE
WHEN 1 THEN o1.name
WHEN 2 THEN o2.name
WHEN 3 THEN o1.name
END,
OBJECT_ID =
CASE au.TYPE
WHEN 1 THEN p1.OBJECT_ID
WHEN 2 THEN p2.OBJECT_ID
WHEN 3 THEN p1.OBJECT_ID
END,
index_id =
CASE au.TYPE
WHEN 1 THEN p1.index_id
WHEN 2 THEN p2.index_id
WHEN 3 THEN p1.index_id
END,
bd.FILE_ID,
bd.page_id,
bd.page_type,
bd.page_level
FROM sys.dm_os_buffer_descriptors bd
INNER JOIN sys.databases d
ON bd.database_id = d.database_id
INNER JOIN sys.allocation_units au
ON bd.allocation_unit_id = au.allocation_unit_id
LEFT JOIN sys.partitions p1
ON au.container_id = p1.hobt_id
LEFT JOIN sys.partitions p2
ON au.container_id = p2.partition_id
LEFT JOIN sys.objects o1
ON p1.OBJECT_ID = o1.OBJECT_ID
LEFT JOIN sys.objects o2
ON p2.OBJECT_ID = o2.OBJECT_ID
WHERE is_modified = 1
AND d.name = 'DirtyPagesDB'
AND
(
o1.name = 't1'
OR o2.name = 't1'
);
GO
确认最后一个检查点的时间
SELECT f1.[Checkpoint Begin], f2.[Checkpoint End]
FROM fn_dblog(NULL, NULL) f1
JOIN fn_dblog(NULL, NULL) f2
On f1.[Current LSN] = f2.[Previous LSN]
WHERE f2.Operation IN (N'LOP_BEGIN_CKPT', N'LOP_END_CKPT');
添加更多行
INSERT INTO t1 VALUES ('SQL'),('Authority')
使用上面的查询确认有脏页
从任务管理器中终止SQL Server任务以模拟关闭电源。
启动服务
重新运行上面的命令以获取最后一个检查点时间,这是相同的(即除我们手动执行的检查点外,没有其他检查点已运行)
从表t1中选择,所有四个记录都在那里