对《SQL Server中tempdb的management》的一些更正和补充

前几天看了这篇文章:SQL Server中tempdb的management

发现里面有些内容不是很准确

文章中说到:

TempDB和其他用户数据库一样以Model数据库为模板创建,并且可以创建和查询表格。

与其他用户数据库不同的是,TempDB在每次SQL Server启动的时候都会被重新创建。

我打开SQLSERVER2005,对比了一下model数据库和tempdb数据库,发现还是有一些不同

初始大小和自动增长跨数据库所有权链接已启用这里不讨论

跨数据库所有权链接:http://www.cnblogs.com/chenxizhang/archive/2009/04/16/1436887.html

页面验证里面,model数据库页面验证用的是checksum,但是tempdb没有页面验证

tempdb不使用页面验证究竟好还是不好???

讨论这个问题之前,这里要先了解一下checksum的功能

以下摘抄自:http://blogs.msdn.com/b/apgcdsd/archive/2012/04/09/sql-2005-checksum.aspx

页面 CHECKSUM:
在数据库页面从被写入磁盘到被SQL Server读取的这段时间内,有可能由于外界原因发生损坏。
比如I/O设备的损坏,驱动的损坏或者由于电源不稳没有写完整。Checksum机制使SQL Server可以检测到这些损坏。
需要注意的是,Checksum机制只能使我们确定是不是I/O子系统引起页面损坏,但是不能自动修复它们。
作为管理员,我们可以利用这些信息来辨识出并更换损坏的I/O设备,
也可以利用重建索引或者修复损坏文件等方法修复已发生的页面损坏。

计算checksum的算法是复杂的,因为会涉及到多个页面的读写,增加CPU的负荷,可能会影响系统的吞吐量

系统吞吐量、CPU负荷这个本人觉得可以忽略不计,因为用户数据库默认都是开启了checksum页面验证的

所以本人觉得还是有必要开启checksum页面验证

页面checksum的条件:在数据库页面从被写入磁盘到被SQL Server读取的这段时间内,数据页一定要写入到磁盘,

如果数据页面没有写入到磁盘,那么开启checksum也就没有什么用处

在tempdb里,无论是数据页还是索引页还是版本存储区里的页面都有可能写入磁盘

版本存储区的资料:http://blogs.msdn.com/b/apgcdsd/archive/2012/03/30/sql-server-tempdb-version-store.aspx

版本存储区也和数据页面索引页面一样由8k大小的页组成。这些页存在缓冲池中,可以在TempDB面临内存压力时被写入磁盘

如果是这样,那么SQLSERVER应该要开启tempdb数据库的checksum页面验证才对啊

很可惜,本人暂时还没有在网上找到相关解释

不过通过下面实验,本人猜测了一些SQLSERVER团队的意图

这些实验在文章SQL Server中tempdb的management里已经给出了,本人只是做一些补充


实验

以下实验的实验环境:Windows7,SQLSERVER2005个人开发者版

全局临时表

通过创建##t_tempdblog全局临时表,插入数据,修改数据,删除数据,建立聚集索引,删除聚集索引,建立非聚集索引,删除非聚集索引

查看事务日志文件里有没有相关的操作记录

测试脚本

插入记录

 use tempdb
go
---------------
-- SETUP
---------------
drop table ##t_tempdblog
go create table ##t_tempdblog (c1 int, c2 char(1000))
go declare @i int
select @i = 0
while (@i < 10)
begin
insert into ##t_tempdblog values
(@i, replicate (cast ('a' as varchar), 1000))
select @i = @i+1
end select top 10 operation,context,
[log record fixed length],
[log record length],
[AllocUnitName]
from fn_dblog(null, null)
where allocunitname='dbo.##t_tempdblog'
order by [Log Record Length] DESC

这个表每行记录应该有char(1000)+4=1004字节

int占用4个字节

char [ ( n ) ]

固定长度,非 Unicode 字符数据,长度为 n 个字节。n 的取值范围为 1 至 8,000,存储大小是 n 个字节。char 的 SQL 2003 同义词为 character。

我们看一下事务日志记录

插入记录到全局临时表并不会记录事务日志

如果将上面那个脚本在用户数据库上执行,输入的日志记录会是下面的样子

用户数据库里的表名是 t_tempdblog

用户数据库会记录插入记录的事务日志信息

修改记录

 UPDATE  ##t_tempdblog
SET c2 = REPLICATE(CAST ('b' AS VARCHAR), 1000) SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.##t_tempdblog'
ORDER BY [Log Record Length] DESC

修改记录会记录到事务日志文件

创建聚集索引

 CREATE CLUSTERED INDEX cix_##t_tempdblog ON [##t_tempdblog](c1)
GO
SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.##t_tempdblog'
ORDER BY [Log Record Length] DESC

建立聚集索引之后连日志都没有了

drop掉聚集索引之后又能看到事务日志了

 DROP INDEX cix_##t_tempdblog ON ##t_tempdblog
GO
--drop 掉聚集索引之后又能看到日志了
SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.##t_tempdblog'
ORDER BY [Log Record Length] DESC

建立非聚集索引

 CREATE  INDEX ix_##t_tempdblog ON [##t_tempdblog](c1)
GO
SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.##t_tempdblog'
ORDER BY [Log Record Length] DESC

事务日志又消失了

建立聚集索引和非聚集索引的时候,全局临时表里是有数据的,大家不要以为我删除了表数据

删除非聚集索引

 DROP INDEX ix_##t_tempdblog ON ##t_tempdblog
GO
--drop 掉聚集索引之后又能看到日志了
SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.##t_tempdblog'
ORDER BY [Log Record Length] DESC

还是没有事务日志记录

删除表数据

 DELETE  ##t_tempdblog
GO SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.##t_tempdblog'
ORDER BY [Log Record Length] DESC


局部临时表

插入数据

 drop table #t_tempdblog
go create table #t_tempdblog (c1 int, c2 char(1000))
go declare @i int
select @i = 0
while (@i < 10)
begin
insert into #t_tempdblog values
(@i, replicate (cast ('a' as varchar), 1000))
select @i = @i+1
end select top 10 operation,context,
[log record fixed length],
[log record length],
[AllocUnitName]
from fn_dblog(null, null)
where allocunitname='dbo.#t_tempdblog'
order by [Log Record Length] DESC

修改数据

 UPDATE  #t_tempdblog
SET c2 = REPLICATE(CAST ('b' AS VARCHAR), 1000) SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.#t_tempdblog'
ORDER BY [Log Record Length] DESC

创建聚集索引

 CREATE CLUSTERED INDEX cix_#t_tempdblog ON [#t_tempdblog](c1)
GO
SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.#t_tempdblog'
ORDER BY [Log Record Length] DESC

删除索引,建立非聚集索引也是一样,没有事务日志记录

删除数据

 DELETE  #t_tempdblog

 SELECT TOP 10
operation ,
context ,
[log record fixed length] ,
[log record length] ,
[AllocUnitName]
FROM fn_dblog(NULL, NULL)
WHERE allocunitname = 'dbo.#t_tempdblog'
ORDER BY [Log Record Length] DESC


猜测原因

从上面的实验可以看到,SQLSERVER不是对所有的操作都写入事务日志,局部临时表完全没有日志记录

可以猜测:SQLSERVER团队认为tempdb里的数据不是那么重要,所以不设置页面验证为checksum验证

但是根据这篇文章:http://blogs.msdn.com/b/apgcdsd/archive/2012/03/19/sql-server-tempdb-tempdb.aspx

触发器:触发器对被删除和被插入的行进行操作,这是原表的 DML 操作的一部分。SQL Server2005之前,触发器通过遍历撤消/重做日志逻辑构造这些行。

因为 SQL Server 需要遍历的旧的记录,这会导致磁盘头来回移动,从而损害的日志所在磁盘的 IO 吞吐量。

通常事务回滚并不常见,日志所在磁盘一般都是有顺序地写入。如果应用程序大量使用触发器就有可能导致日志磁盘上的 IO 瓶颈。

自SQL Server 2005开始,触发器改为使用行版本。于是被删除的和被插入的行将使用行版本,这些行的句柄将附加到该事务中。

使用行版本避免了SQL Server遍历日志,从而减小了日志磁盘压力,但同时行版本增加了TempDB的使用量。

在线索引:索引可以在线创建,但创建的同时行的数据可能会发生改变。SQL Server使用行版本保证创建索引参考的数据不被改变。

MARS:MARS全称为Multiple Active Result Sets(多个活动结果集)。SQL Server通过行版本实现它。这是一个较为复杂的功能。

概括的说就是因为MARS允许同一事务内的多个语句在同一时间处于活动状态,SQL Server 就必须使用行版本控制来提供语句级别的一致性。

快照隔离级别和使用行版本控制的已提交读隔离级别:行版本是实现这些新隔离级别的基础。SQL Server 创建已修改的行版本,

使这些隔离级别下运行的事务不会读到脏数据。

DBCC CHECKDB:生成数据库的快照,再对数据库进行checkdb检查

还有一些功能用到tempdb的,例如版本存储区,这里就一一详细列出来了

本人觉得这些功能都非常重要的,承载的数据也很重要

在SQLSERVER2012里面,tempdb的数据库选项有些不一样,可能从SQLSERVER2008开始就不一样,不过由于本人

没有安装SQLSERVER2008,先不说SQLSERVER2008,先看一下SQLSERVER2012


SQLSERVER2012里model数据库和tempdb数据库选项的比较

可以看出SQLSERVER2012已经将tempdb的页面验证改为checksum了

如有不对的地方,欢迎大家拍砖o(∩_∩)o

对《SQL Server中tempdb的management》的一些更正和补充的更多相关文章

  1. SQL Server中tempdb的management

    对<SQL Server中tempdb的management>的一些更正和补充   对<SQL Server中tempdb的management>的一些更正和补充 前几天看了这 ...

  2. SQL Server中tempdb的管理

    原文:SQL Server中tempdb的管理 资料来自: http://blogs.msdn.com/b/sqlserverstorageengine/archive/tags/tempdb/ ht ...

  3. SQL Server中TempDB管理(version store的逻辑结构)

    原文:SQL Server中TempDB管理(version store的逻辑结构) 原文来自: http://blogs.msdn.com/b/sqlserverstorageengine/arch ...

  4. SQL Server中TempDB管理(版本存储区的一个example)

    原文:SQL Server中TempDB管理(版本存储区的一个example) 原文来自: http://blogs.msdn.com/b/sqlserverstorageengine/archive ...

  5. [转]如何监测谁用了SQL Server的Tempdb空间

    Tempdb 系统数据库是一个全局资源,供连接到 SQL Server 实例的所有用户使用.在现在的SQL Server里,其使用频率可能会超过用户的想象.如果Tempdb空间耗尽,许多操作将不能完成 ...

  6. SQL Server中的TempDB管理——TempDB基本知识(为什么需要版本存储区)

    原文:SQL Server中的TempDB管理--TempDB基本知识(为什么需要版本存储区) 参考资料来自: http://blogs.msdn.com/b/sqlserverstorageengi ...

  7. SQL Server 中如何移动tempdb到新的位置

    操作步骤:1.检查tempdb的逻辑名字和它的存在位置.可以使用下面语句: SELECT name, physical_name FROM sys.master_files WHERE databas ...

  8. SQL Server中关于跟踪(Trace)那点事

    前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案. 简 ...

  9. 【转】SQL Server中关于跟踪(Trace)那点事

    前言 一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案. 简 ...

随机推荐

  1. android GridLayout布局

    android4.0版本后新增了一个GridLayout,它使用虚细线将布局划分为行.列和单元格,也支持一个控件在行.列上都有交错排列,其实用方法和LinearLayout,Relativelayou ...

  2. Android 开发工具类 14_ JsonTools

    天气 JSON 数据解析 package com.example.weather_json.tools; import java.util.ArrayList; import java.util.Li ...

  3. [C语言]类型限定词const解析

    作为C90增加的一个受限类型关键字,const赋予了它修饰的变量一个新属性——不变性,如果一个变量声明中带有关键字const,则无法通过赋值.增减运算来修改该变量的值. 一.指针与const结合 co ...

  4. 前端JS校验银行卡卡号和身份证号码(附ES6版方法)

    1.银行卡卡号校验方法. function luhnCheck(bankno) { var lastNum = bankno.substr(bankno.length - 1, 1); //取出最后一 ...

  5. 关于打开fiddler后电脑无法正常上网的解决办法(fiddler抓包时的设置)

    关于fiddler如何抓取  ie内容(其中:360浏览器和qq浏览器均使用ie内核) 1.打开fiddler,进入tools-options,设置如下.这样配置后,打开fiddler,fiddler ...

  6. Android应用博客目录

    应用有很多,开个博客都放进来方便查找,也方便修改 1 语言类: 1.1 JAVA 基础语言知识JAVA Collection与Collections,Array与Arrays的区别 JAVA练手--S ...

  7. Oracle官网下载参考文档

    最近有人问我有没有Oracle11g数据库官方参考文档,我就想,这不是在官网可以下载到的吗,疑惑,问了之后才知道,他官网找过,但时没有找到.不要笑,其实有很多人一样是找不到的,下面就一步一步操作下: ...

  8. 【JavaScript 从零开始】变量作用域

    变量作用域 一个变量的作用域(scope)是程序源代码中定义这个变量的区域. 全局变量拥有全局作用域,在JavaScript代码中的任何地方都是有定义的.然而在函数内声明的变量只是函数体内有定义. 他 ...

  9. 美图吴欣鸿:请不要叫我CEO

    关于采访提纲上“对互联网+如何理解?”的问题能否不做回答? 他的说法听上去谦虚而实在,“我一般对于这种大的.有点政策性的问题其实是Hold不住的,我的谈话风格就是比较随性.感性,也很难说去推出一个很强 ...

  10. [日常] go语言圣经-获取URL练习题

    1.主要使用net/http和io/ioutil包 2.http.Get函数是创建HTTP请求的函数,resp这个结构体中,Body字段包括一个可读的服务器响应流 3.ioutil.ReadAll函数 ...