Microsoft SQL Server 2005技术内幕:存储引擎笔记
Microsoft SQL Server 2005技术内幕:存储引擎笔记
目录
f
f
f
f
f
f
f
f
f
f
f
第一章sqlserver的安装升级
f
f
f
f
评估版只有120天期限
f
所有版本都集成.net 2.0框架,不需要单独下载
f
每个物理CPU只需要一个许可证,无论单个物理cpu多少线程
f
f
f
f
运行sqlserver服务的系统账户要设置密码永不过期,否则密码过期sqlserver启动不起来
f
字符集和排序规则
f
f
代码页就是字符集,两者相等
两个字节存储一个字符
f
f
f
f
f
排序规则的改变也会作用于系统表
f
二进制排序
bin
在大小写敏感或重音敏感的情况下,我们可以选择二进制排序操作,在二进制排序中,字符是根据他们的内部字节表示排序的。
在一个二进制排序中,字符遵照他们的存储位置的值排序,就好像他们在图中的顺序。根据定义,我们可以得出一个二进制排序总是大小写敏感的,同时也是重音敏感的,每一个字符都有一个唯一的字节值
二进制排序是最快的排序操作,因为他们的操作只是对那些值进行简单的一个字节,一个字节比较。
在大小写敏感的字典排序中abcxyzABCXYZ跟AaBbCcXxYyZz的排序是一样的。在二进制排序中,所有的大写字母都会出现在任何小写字母之前,例如
ABCXYZabcxyz
f
安装sql2005的过程会要求指定服务器的默认排序规则,这个就是系统数据库会用到的排序规则,而且任何一个之后创建的新数据库都会默认使用这个排序规则
使用默认排序规则并不是唯一的选择
Windows排序规则
SQL排序规则
SQL_Latin1_General_CP1_CI_AS
Latin1_General
Latin1_General表示unicode的排序次序是字典排序
CP1表示默认代码页是1252 codepage
CI_AS表示大小写不敏感,重音敏感
其他的排序规则都使用完整的代码页数字,只有1252有特殊的缩写CP1
例如 SQL_Scandinavian_CP850_CS_AS:表示SQL排序规则,对unicode数据使用Scandinavian排序次序,非unicode的代码页是850,排序次序是大小写敏感,重音敏感
f
SQL排序规则是只对早前sqlserver版本向后兼容,并不是每一个排序次序,unicode排序规则和代码页的组合都是可能的
Windows排序规则中,unicode数据类型总是和非unicode数据类型使用相同的排序行为
Windows排序规则从我们的Windows操作系统配置中取得的特定的值作为排序规则的默认值
二进制排序使用很少的CPU指令,但是大多数sqlserver中,排序趋势都趋向于I/O,而不是CPU
因为数据存到数据库里都是字节,那么二进制排序直接取字节直接排序,CPU消耗少,不需要额外运算,而且空间也少
f
F
计算机名为实例名的实例为默认实例
F
F
实例无关服务,所有实例共享
F
32767resource数据库的ID
SYS前缀
F
F
F
升级的内幕
F
升级之后,元数据会发生改变,特别sqlserver7.0,2kb的页面变为8kb
配置DTS包到SSIS
重新配置日志传送
重建SSAS多维数据集
F
F
数据库的兼容性级别控制着新的保留字是否能在不加引号的情况下被识别出来,还控制着某些语法结构是不是可以识别的
如果一个数据库停留在一个之前的兼容性级别上,那么sqlserver新版本中的一些新功能就无法使用了
f
f
通知服务
notification services是一个环境,他是为开发和部署那些生成和发送通知的应用程序而服务的。我们可以使用通知服务来及时生成和发送私人消息给成千上万的订阅用户
另外也可以传送消息给不同的设备
f
f
第二章sqlserver体系结构
f
f
f
命名管道为lan局域网而开发的协议
tds端点
[tcp_endpoints]
端点:endpoint
f
缓存区管理器-》缓冲区
f
f
f
f
f
sqlserver6.5的时候还是使用SMP架构
每个numa节点所包含的cpu数量取决于硬件供应商,访问本地节点内存的速度会比访问其他numa节点所关联的内存要快一些,这就是称之为非一致性内存访问的原因
sql2005允许我们将一个或多个物理numa节点拆分为更小的numa节点,参考软nuam或软件numa
由于软numa只能拆分cpu不能拆分内存,一般来讲当我们没有硬件numa但是却有很多cpu时,可以使用软numa。我们还可以使用软numa来将硬件numa节点拆分成包含cpu数量比硬件numa更少的分组
f
软numa节点经过配置也可以在自己的端口进行监听,分流
将 SQL Server 配置为使用软件 NUMA (SQL Server)
http://technet.microsoft.com/zh-cn/library/ms345357.aspx
将 TCP/IP 端口映射到 NUMA 节点 (SQL Server)
http://technet.microsoft.com/zh-cn/library/ms345346.aspx
纤程
f
每个worker如果空闲时间超过15分钟或sqlserver内存紧张,就可能被销毁
每个worker在32位系统中至少可以使用0.5MB内存,在64位系统中至少可以使用2MB内存
注意:是至少
f
看schedulers工作负载
SELECT [load_factor],* FROM sys.[dm_os_schedulers]
纤程模式实际上是为了某些特殊场合和情况而设计的,在这些场合由于花费太多时间在线程上下文和用户态和核心态之间进行切换,sqlserver的可扩展性达到极限
f
SELECT * FROM sys.[sysprocesses] WHERE [cmd]='RESOURCE MONITOR'
每个numa节点都有自己的惰性写入器和资源监视器,他由一个隐藏的调度器来管理
资源监视器也有自己的spid
每个numa /scheduler节点都有自己的调度器监视器,他能够在任何spid上运行并运行在抢占模式
每个节点还有自己的I/O竞争端口IOCP,该端口是网络监听器
探针:探测资源的空闲
当设置了关联掩码,其中一些调度器会设置为离线也不会有任务分配给他们
f
跟踪标志8002不限制某一个调度器在某个特定的cpu上运行
f
[load_factor]
sql2005中路由决策是根据调度器的负载来做出的
f
SPINLOOP:等待一个信号时,陷入一个自旋锁
f
SELECT t2.[session_id] FROM sys.[tcp_endpoints] AS t1 JOIN sys.[dm_exec_sessions] AS t2 ON t1.[endpoint_id] = t2.[endpoint_id] WHERE [t1].[name] = 'dedicated admin connection'
f
DAC分配有一个特殊的线程允许他在一个单独的调度器上执行诊断函数和查询
这个线程不能被杀掉,在需要的时候我们仅能杀掉DAC会话
DAC没有惰性写入器线程,但是有自己的IOCP,一个工作线程和一个空闲线程
sqlserver express版本只有开启跟踪标志7806才支持DAC
f
F
LRU-K算法,这种算法是对严格的LRU置换策略的巨大改进
sql2005使用的K值为2,也就是他会跟踪系统对每个缓冲区页最近两次的访问
自由页面列表
SQLSERVER 里经常看到的CACHE STORES是神马东东?
http://www.cnblogs.com/lyhabc/p/3774181.html
F
每个sqlserver实例对每个numa节点都有一个相应的惰性写入器线程,他能够扫描与numa节点关联的高速缓存
惰性写入器通过扩张和缩小数据缓存将操作系统的自由物理内存保持在5MB以上或再减去200KB,以防止换页过多,
如果操作系统的自由内存少于5MB,那么惰性写入器会释放内存给操作系统而不是将内存加入free list
Ff
f
checkpoint触发的条件
估计出恢复时间非常之长
必须有至少是最小量的工作完成才能触发checkpoint,这个最小量当前是每分钟10MB日志量。
以这种方式,sqlserver不会浪费时间在空闲的数据库上执行checkpoint
shutdown with nowait不会在每个数据库上执行checkpoint
f
跟踪标志3502将相关checkpoint信息写入errorlog
checkpoint操作的聚集写入和生成号
通用缓存框架,除数据高速缓存之外的所有高速缓存都用到了他
该框架包含了一套存储仓库 cachestore和资源监视器
一共有三种类型的cachestore
高速缓冲cachestore(plan cache)
用户cachestore(实际上与用户并没有任何关系) (元数据)
对象cachestore
对象cachestore 仅仅是内存块组成的内存池,并不需要LRU或成本计算
对象cachestore(例如 SNI 网络接口 作为网络缓冲池 结果集?)
f
--时钟
SELECT [removed_last_round_count] FROM sys.[dm_os_memory_cache_clock_hands]
SELECT [removed_last_round_count] FROM sys.[dm_os_memory_cache_clock_hands]
[removed_last_round_count] bigint类型
SELECT * FROM sys.[dm_os_memory_cache_clock_hands]
如果[removed_last_round_count]列增长非常迅速,那么这就是存在内存压力的强烈信号
微软在sql2005开发周期的晚期引入了内存经纪broker
内存经纪的工作是分析sqlserver有关内存消耗的行为并改善动态内存分配
内存经纪是一种中央控制机制
f
环形缓冲区ring_buffers不是sqlserver2008才有的
SELECT * FROM sys.[dm_os_ring_buffers] WHERE [ring_buffer_type] = 'ring_buffer_memory_broker'
--利用Ring Buffer在SQL Server 2008中进行连接故障排除 SELECT CAST(record AS XML) FROM sys.dm_os_ring_buffers WHERE ring_buffer_type = 'RING_BUFFER_CONNECTIVITY'
SELECT [type],SUM([multi_pages_kb]) FROM sys.[dm_os_memory_clerks] WHERE [multi_pages_kb]!=0 GROUP BY [type]
这些页面都不是在buffer pool里面的,而且大于8kb
sqlserver包含三部分内存:buffer pool,buffer pool外的multi page,awe部分的内存
当sql启动时,他会计算sqlserver进程的虚拟地址空间(VAS)的大小
每个运行在Windows上的进程都有自己的VAS。所有可供进程使用的虚拟地址的集合构成了VAS的大小。VAS的大小取决于体系结构和操作系统。
VAS只是所有可能地址的集合,他可以比计算机上的物理内存大很多
f
f
除了虚拟地址空间的大小,sqlserver还会计算一个称为目标内存(target memory)的值,这是预期可以分配的8KB页面的数目。如果设置了配置选项-最大服务器内存(max server memory),那么目标内存就是这两个值中的较小者。sqlserver对目标内存会周期性地进行重新计算,特别是他收到来自Windows的内存通知时。
在一个负载正常的sqlserver上发生目标页面数目减少的可能原因是来自外部物理内存压力。我们可以通过性能监视器--检查sqlserver:内存管理对象(memory manager object)中的目标服务器页面(target server page)计数器来查看目标页面的数量
sqlserver不一开始就获得等于最小服务器内存的内存量
f
要查看这些DMV,需要有view server state权限
SELECT DISTINCT * FROM sys.[dm_os_memory_clerks]
[dm_os_memory_clerks]为sql实例上每个内存经纪返回一行,我们可以认为一个内存经纪就是一个计算单位。
前面描述过的每个cachestore都是一个内存经纪,但是有一些经纪(例如 CLR经纪和全文检索经纪)并不是cachestore
f
SELECT * FROM sys.[dm_os_memory_cache_counters]
SELECT * FROM sys.[dm_os_memory_cache_hash_tables]
--为sqlserver实例中的每个活动的高速缓存返回一行 hashtable SELECT * FROM sys.[dm_os_memory_cache_hash_tables] AS hashtb INNER JOIN sys.[dm_os_memory_cache_counters] AS cachecnt ON [cachecnt].[cache_address] = [hashtb].[cache_address] --为用户cachestore和高速缓存cachestore的每个高速缓存返回一份关于其健康情况的快照 SELECT [buckets_avg_scan_hit_length] FROM sys.[dm_os_memory_cache_hash_tables] --[buckets_in_use_count] 当前使用的存储桶数 --[buckets_avg_scan_hit_length] 在找到搜索项之前,存储桶中已检查条目的平均数,就像前面那样,如果该数字很大,那么意味着高速缓存并不是最优的 --可以考虑运行DBCC FREESYSTEMCACHE来移除高速缓存cachestore中所没有使用的条目。联机丛书对这个命令有更详细描述 --就像上面讨论那样,这个DMV可以通过cache_adress列与其他高速缓存DMV进行连接操作 SELECT * FROM sys.[dm_os_memory_cache_clock_hands] SELECT * FROM sys.[dm_os_memory_cache_hash_tables] AS hashtb INNER JOIN sys.[dm_os_memory_cache_clock_hands] AS cacheclock ON [cacheclock].[cache_address] = [hashtb].[cache_address] --[removed_all_rounds_count] 时钟表针在所有的周转中删除的条目数
f
DBCC memorystatus
f
numa节点的非本地内存,不等同于外部内存
一次多达2MB的预读量 32个区(32*8页/区*8192字节/页=2MB)
使用单次256kb分散读取可以一次读取四个区(32个页面)
f
第三章 sql2005 配置
f
f
f
f
f
f
f
在sqlserver7.0以前必须手工配置所有内存选项就像mysql一样
包括sqlserver总共使用多少内存,这其中有多少内存应该作为特定用途使用
max server memory的默认值是214783647 实际上是底层系统表的int型值可以存储的最大值跟系统中的实际资源无关
f
建议不要将user connection设置得太高,因为无论是否被使用,每条连接都会占有大约28KB的额外开销
f
每个锁要消耗96个字节
64位操作系统:每个锁块需要96个字节。每个锁拥有者块需要56个字节 0.5MB
共有5个选项会影响调度程序的行为:Lightweight pooling纤程池
affinity mask,affinity64 mask,priority boost,max worker threads
4字节的关联掩码可以最多支持32个处理器
f
sqlserver默认运行在线程模式下,如果设置运行在纤程模式下,那么纤程池的维护比线程容易得多
但是linkedserver和扩展存储过程还是要切换到线程模式,切换开销会很大
提升sqlserver优先级,如果DB和程序运行在同一台机器,那么会使程序饿死,因为程序得不到运行的cpu资源
f
f
调节预读的选项没有了,所有磁盘操作都由sqlserver自行处理
f
sqlserver会在日志达到容量的70%时执行一次checkpoint
一个主要用于读操作的数据库是不会频繁checkpoint的
f
最小查询内存min memory per query
排序,merge join ,hash join都需要大量内存,最好不要设置这个值
f
f
设置阻塞报警时间 blocked process threshold是sql2005新增的一个选项
f
索引创建内存
查询控制器开销限制
最大并行度
f
并发度DOP由许多因素决定,包括关联掩码设置,最大并行度设置,以及查询开始执行时系统中的可用线程数
f
sql2000中的allow updates(允许更新系统表)选项依然存在但在sql2005中不起作用
f
SELECT * FROM sys.[configurations] ORDER BY [name]
f
f
f
f
f
默认跟踪
f
默认跟踪是sql2005新增的
默认跟踪的写入是以128KB的区块为单位进行,写文件以128KB区块进行,每次写入磁盘都需要达到128KB才能进行,当sql停止时,所有跟踪时间都会写磁盘
与sql2000的blackbox 黑盒跟踪不同
f
默认跟踪捕捉的事件列表如下
f
用户不能修改默认跟踪的保存位置,也无法添加或删除事件,以及可能应用到事件上的过滤器
f
第四章 数据库和数据库文件
f
f
f
f
f
我们可以通过在补丁包service pack(sp)里简单地置换新的resource数据库来将他升级到引入了新的系统对象的补丁
resource数据库的创建和修改日期都是这个sqlserver实例的当前service pack的代码启用日期
SELECT @@VERSION Microsoft SQL Server 2005 - 9.00.4035.00 (X64) Nov 24 2008 16:17:31 Copyright (c) 1988-2005 Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)
f
f
service broker也会使用到msdb数据库,他提供队列和可靠消息传递
f
f
northwind是最初为微软access开发的示例数据库
f
数据库文件
f
sys.database_file视图
type 文件类型
0 数据行
1 日志
2 保留
3 保留
4 全文索引文件
f
f
data_space_id 该文件所属数据空间ID,数据空间是一个文件组
0 =日志文件
state
0 =在线
1=还原中
2=恢复中
3=等待恢复中
4=置疑
5=保留
6=离线
7=死亡
size 文件当前大小,单位为页面8KB
日志文件最大能增长到2TB
f
f
model库包含47个对象,41张系统表,6个为notification service和service broker所使用的对象
F
运行sp_help存储过程,他会列出多达1788个对象,事实上这些对象大多数并不是真正存在在model数据库中的
F
F
F
收缩数据库或任何的数据文件都是非常消耗资源的操作,只有在非常有必要恢复磁盘空间时才有必要进行这种操作
f
快速文件初始化
将用户加入卷维护任务
如果我们要确保数据文件在创建或增长时填零,可以使用traceflag1806
他会像之前版本sqlserver一样总是对创建或增加的空间填零
自动收缩数据库选项
自动收缩数据库的spid总是6
sql2005
f
f
f
shrinkdatabase的机制跟shrinkfile机制一样,sqlserver首先将页面移动到文件前部来释放后部空间,之后再释放合适数量的自由页面给操作系统
f
f
currentsize是指在数据库收缩之后的以页面计算的大小。在这个例子中,数据库文件(fileid=1)收缩到256个8KB页面,也就是2MB大小。但是实际上仅仅有152个页面被使用到。造成实际使用页面和当前页面数量不同的原因有以下几个
如果model数据库数据文件的大小比实际使用的页面大小要大,那么当前大小将不能变得比model数据库的数据文件还小
对于日志文件(fileid=2)而言,真正有意义的值仅有当前值和最小值。其余的两个值对日志文件来讲基本上是没有意义的,因为当前大小总是和实际使用的页面大小相同的,并且没有一种简单的方法来估计一个日志文件能够被收缩到多小
收缩一个日志文件与收缩一个数据文件非常不同
f
f
f
f
段落还原一定要先还原主文件组,一旦主文件组还原完毕,数据库就马上可用
段落还原还需要我们有日志备份
f
f
更改数据库 alter database
向数据库中增加一个或多个日志文件
从数据库移除一个文件或文件组,只有在文件或文件组为空的情况下才可以这样做
f
我们不能将一个文件从一个文件组移动到另一个文件组
f
f
f
f
f
GAM页面和SGAM页面
每一个数据文件的页码为0的页面是fileheader页面,并且每个文件仅有一页
f
IAM页面
IAM页面在4G空间中跟踪被分配单元所使用的区,一个分配单元就是一组页面,这些页面属于一个数据表或索引的单个分区
f
SELECT [allocation_unit_id],[type_desc],[container_id],[first_page],[root_page],[first_iam_page] FROM sys.[system_internals_allocation_units]
称为[system_internals_allocation_units]的内部系统视图有一个称为[first_iam_page]的列指向一个分配单元的第一个IAM页面。那个分配单元的所有IAM页面组成了一个链表,每个IAM页面含有一个指针指向该链表中的下一个页面
dbcc
dbcc在sql2000以前版本的sqlserver中所代表的意思是数据库一致性检查器(database consistency checker)。然而,微软从sybase获取该产品的代码之后,DBCC开始具备越来越多的功能,并最终超出了单纯的一致性检查范围
从sqlserver2000开始,微软将DBCC定义为数据库控制台命令database console command
并将dbcc分为四种类型:校验类、维护类、信息类、其他类
校验类命令 实际上就是check命令:checktable,checkdb。。。。。。
还有两个分别是DBCC CHECKIDENT、DBCC CHECKCONSTRAINTS
表和维护类的DBCC命令:DBCC CLEANTABLE、DBCC UPDATEUSAGE
f
f
dbcc checkdb 首先检查GAM,SGAM,IAM页面中的信息
f
检查GAM和SGAM页面有没有被分配,检查每一个分配单元校验IAM链表
最后 DBCC CHECKALLOC校验所有标记为已分配给分配单元的区确实被分配了
DBCC CHECKTABLE 运行在数据库中的每张表和索引视图之上
检查索引视图通过从底层的select语句定义来重构该视图的行集,并将结果与存储在索引视图中的数据相比较
sqlserver在两个行集之间执行两次left-anti-semi连接来确定一个行集中有的行在另一个行集也存在
DBCC CHECKCATALOG在不同的元数据表之间执行超过50次的交叉验证
f
f
在sql2005中,所有的DBCC校验命令都会使用数据库快照技术来防止校验操作干扰正在进行的数据库操作
所有被检查的数据都不需要加锁
f
由于DBCC CHECKDB的修复选项要在单用户模式下,所以修复的时候也可以不加 WITH TABLOCK
DBCC CHECKDB([sss],REPAIR_ALLOW_DATA_LOSS) WITH TABLOCK
我们可以是with(tablock)选项来避免创建快照
--使用ESTIMATEONLY选项估计checkdb需要多少tempdb空间 DBCC CHECKDB([sss]) WITH ESTIMATEONLY
Estimated TEMPDB space needed for CHECKALLOC (KB)
-------------------------------------------------
26
(1 行受影响)
Estimated TEMPDB space needed for CHECKTABLES (KB)
--------------------------------------------------
158
f
purity:纯度
sql2005创建的所有新数据库在默认情况下都启用了data_purity逻辑型校验
f
数据库开启了checksum选项的时候,所有的sql2005新数据库默认情况下就启用了该选项,在DBCC CHECKDB读取页面时会进行checksum操作
有错误的页面会存储在msdb的suspect_pages表中
f
f
对几乎所有的服务器错误运行修复都会丢失一些数据
在修复期间,不会试图维护表上或表间的任何约束,都例如GAM,SGAM页面损坏或不可读的错误,sqlserver不会去修复
我们在打算使用REPAIR_ALLOW_DATA_LOSS选项时候,应该在执行前先备份数据库,因为运行后会有某些页面释放,数据记录对比不出来
DBCC 操作中的每一个单独的修复都在自己的系统事务中运行
f
如果对DBCC修复的一部分作出的修改不满意,我们可以回滚该修复操作
DBCC CHECKDB,DBCC CHECKTABLE,DBCC CHECKFILEGROUP都有进度报告,可以查询
SELECT * FROM sys.[dm_exec_requests]
DBCC CHECKALLOC 不包含进度报告,因为检查元数据很快,所以这个命令不需要进度报告
f
确保tempdb有足够空间来运行DBCC命令
我们可以使用 DBCC CHECKDB([sss]) WITH ESTIMATEONLY 来预估DBCC命令需要多少tempdb空间
只有在最后一步才考虑使用REPAIR_ALLOW_DATA_LOSS
f
f
SELECT * FROM sys.[sysdatabases]
--数据库选项的完整列表分为七大类:状态选项,游标选项,自动选项,参数化选项,SQL选项,数据库恢复选项,外部访问选项
--还有一些针对SQLSERVER使用的一些特殊技术选项,包括数据库镜像,service broker活动和快照隔离
f
数据库选项
date_correlation_optimization 日期相关优化
f
f
f
f
在限制用户模式下(restricted_user)模式下的数据库只能接受被认为是“合格”用户的连接-这些用户属于dbcreateor或sysadmin服务器角色,或者是那个数据库的db_owner角色的成员
将数据库标记为离线时,数据库的所有快照也都会自动删除
f
如果还原数据库的过程中,磁盘不够空间,那么数据库会被设置为recovery_pending
f
如果还原过程中探测到有故障,那么数据库会置疑,置疑的时候sp_helpdb也无法看打该数据库
ALTER DATABASE [sss] SET EMERGENCY ,当我们将recovery_pending模式转换到紧急模式时,sqlserver关闭该数据库,然后使用一个允许他跳过恢复过程的特殊的标志位重新启动该数据库。跳过恢复过程意味着会出现一些在逻辑上或物理上不一致的数据--丢失索引行,损坏的页面链接或不正确的元数据指针
设置为EMERGENCY 紧急模式的时候,事务日志会被禁用,数据库设置为只读状态read_only,并且对数据库的访问只限于sysadmin角色的成员
f
使用紧急模式的DBCC CHECKDB会使用由于I/O或校验和checksum错误已经被标记为无法访问的页面,就好像这些错误还没有发生一样
跳过无法访问的页面
如果数据库恢复没有成功,会重建事务日志,重建日志会破坏事务一致性
如果DBCC CHECKDB成功,我们可以运行DBCC CHECKCONSTRAINTS([aaa])[aaa]为表名找出所有业务逻辑方面的错误,并且马上备份数据库
如果DBCC CHECKDB失败,那么数据库就报废了
在某些情况下,紧急模式不是万能的,特别是当与空间分配有关的一些元数据(数据库启动时需要这些数据时)丢失或损坏的时候
f
当DBCC CHECKDB完毕后,我们可以尝试将数据库设置为在线,如果在线模式转变无法完成,那么数据库或者停留在recovery_pending或置疑suspect状态
再次强调一下,我们可以将恢复中断recovery_pending状态的数据库切换到紧急模式来使得数据库能够被读取
f
这时候无论我们使用何种方式来尝试更新数据,都会收到下面的错误
msg 3908, level 16, state 1, line1 could not run begin transaction in database 'testdb' because the database is in bypass recovery mode the statement has been terminated
如果将数据库状态切换回在线,我们会收到一个指出无法进行恢复的错误,并且数据库将被重新设置为恢复中断recovery_pending模式。前面提到过,在紧急模式下运行带repair选项的DBCC CHECKDB命令使可以修复的数据库重新上线
在只读模式下,重启数据库时不会在该数据库上运行自动恢复,并且所有select操作都不会获得锁,在只读模式下收缩数据库是不可能的
f
f
--termination选项
ALTER DATABASE [sss] SET READ_ONLY WITH ROLLBACK AFTER 1
--ROLLBACK AFTER integer [SECONDS]这个选项会使sqlserver先等待指定的秒数后,然后
--中断不合格的连接,不完整的事务会被回滚.当切换到单用户(single_user)模式时,除了发出
--alter database语句的连接,所有的连接都被当作不合格的连接.当切换到限制用户(restrict_user)
--模式时,不合格的连接不仅包括那些非db_owner固定数据库角色成员的连接,还包括那些非dbcreateor
--而且非sysadmin固定服务器角色成员的连接
alter database的连接不会杀掉
ALTER DATABASE [sss] SET READ_ONLY WITH ROLLBACK IMMEDIATE
--ROLLBACK IMMEDIATE 马上中断不合格的连接,所有尚未完成的事务都会回滚.要注意的是也许连接
--马上中断,回滚却需要一些时间来完成.事务所有的工作都必须撤销,所以对某些特定操作,例如一个对
--数百万行数据进行更新的批处理操作,或者对一个大型索引的重建操作,我们可能需要等待很久.
--这里不合格的连接和前面描述的不合格连接相同
ALTER DATABASE [sss] SET READ_ONLY WITH NO_WAIT
--NO_WAIT 会使得sqlserver在尝试改变数据库状态之前检查连接,并且当某些连接存在时该选项会
--导致alter database语句失败。如果数据库设置为single_user模式,当存在任何其他连接时
--alter database语句都会失败,如果是切换到限制用户模式,当存在不合格用户的连接时,alter
--database语句都会失败
NO_WAIT就格杀勿论,不管是alter database的连接还是什么连接
f
但是测试发现NO_WAIT还是杀不了连接
ALTER DATABASE [sss] SET READ_ONLY WITH NO_WAIT 消息 5070,级别 16,状态 2,第 1 行 在其他用户正使用数据库 'sss' 时,无法更改数据库状态 消息 5069,级别 16,状态 1,第 1 行 ALTER DATABASE 语句失败。
f
f
自动选项
auto_close
f
f
数据库选项
date_correlation_optimization 日期相关优化
f
允许带引号的标识符 QUOTED_IDENTIFIER:如果是ON,那么sqlserver的关键字也可以作为表名和列名,可以使用sqlserver的关键字,如果为off,那么会报错在实验关键字的时候
f
f
重新计算校验和并和页面头部的校验和进行比较
不见页面头部有checksum值
f
sqlserver将会对任何校验和,损坏页和其他I/O错误进行四次重试操作
如果四次操作都失败,那么会发出824错误
我们可以还原备份或者当错误出现在索引时,重建索引来修复错误,如果遇到checksum错误,我们可以运行DBCC CHECKDB来确定受影响的数据页面类型和数据页
512字节,一般盘符分配单元可以设置为512字节,日志写入的单位一般是512字节,每个磁盘扇区可以存放512个字节的信息
f
f
f
f
创建数据库快照必须使用TSQL语句
创建快照时,我们必须在CREATE DATABASE命令中包含源数据库中的每一个数据文件,包括原来的逻辑名称和一个新的物理名称,不能够指定其他的文件属性,不能指定日志文件
CREATE DATABASE [AdventureWorks_snapshot] ON (NAME=N'adventureworks_data',FILENAME='C:\aw_snapshot.mdf') AS SNAPSHOT OF [AdventureWorks];
稀疏文件以64KB为单位增量增长,稀疏文件的大小总是64KB的倍数
写入时复制(copy-on-write)
f
f
创建快照时在源数据库会进行checkpoint操作,并将一个lsn号记录在源数据库的日志文件里
如果在创建快照时有长事务运行,那么会在数据库快照可用前撤销未提交的事务,所以该快照会包含修改后数据的源数据库所有页面的原始版本
f
f
SELECT * FROM sys.[dm_io_virtual_file_stats](DB_ID(),FILE_ID())通过DMF发现数据库快照的每个稀疏文件正在使用磁盘上的字节数是多少,该函数通过size_on_disk_bytes列返回一个文件中的当前字节数。
在Windows资源管理器里显示出的size值是最大值,磁盘上的大小应该跟我们dm_io_virtual_file_stats看到的大小相同
f
数据库快照是不能使用DBCC CHECKDB修复的,特别是被置疑的快照,所以不一定能从快照恢复好源数据库
f
如果一个源数据库存在快照,那么源数据库就无法删除,分离,还原
我们可以把源数据库进行离线offline
我们可以把源数据库回复到revert到快照创建的时间点
RESTORE DATABASE [AdventureWorks] FROM snapshot =[AdventureWorks_snapshot]
当存在多个快照时,我们是不能回复到其中任何一个快照的,所以我们首先应该把除了希望回复的快照以外的所有快照删除,删除快照的操作跟drop database方法一样,在删除快照的同时,所有NTFS稀疏文件也都被删除
F
F
tempdb记录的日志只能被回滚undo不能被重做redo,因为根本不需要重做,因为tempdb会定时重建,而且简单模式
DBCC CHECKDB([tempdb]) tempdb的 DBCC 结果。 DBCC CHECKDB 将不检查 SQL Server 目录或 Service Broker 一致性,因为无法创建数据库快照或指定了 WITH TABLOCK。 sys.sysrscols的 DBCC 结果。 对象 'sys.sysrscols' 的 12 页中有 894 行。 sys.sysrowsets的 DBCC 结果。 对象 'sys.sysrowsets' 的 2 页中有 130 行。 sys.sysclones的 DBCC 结果。 对象 'sys.sysclones' 的 0 页中有 0 行。 sys.sysallocunits的 DBCC 结果。 对象 'sys.sysallocunits' 的 2 页中有 144 行。 sys.sysfiles1的 DBCC 结果。 对象 'sys.sysfiles1' 的 1 页中有 2 行。 sys.sysseobjvalues的 DBCC 结果。 对象 'sys.sysseobjvalues' 的 0 页中有 0 行。 sys.syspriorities的 DBCC 结果。 对象 'sys.syspriorities' 的 0 页中有 0 行。 sys.sysdbfrag的 DBCC 结果。 对象 'sys.sysdbfrag' 的 0 页中有 0 行。 sys.sysfgfrag的 DBCC 结果。 对象 'sys.sysfgfrag' 的 0 页中有 0 行。 sys.sysdbfiles的 DBCC 结果。 对象 'sys.sysdbfiles' 的 1 页中有 2 行。 sys.syspru的 DBCC 结果。 对象 'sys.syspru' 的 0 页中有 0 行。 sys.sysbrickfiles的 DBCC 结果。 对象 'sys.sysbrickfiles' 的 0 页中有 0 行。 sys.sysphfg的 DBCC 结果。 对象 'sys.sysphfg' 的 1 页中有 1 行。 sys.sysprufiles的 DBCC 结果。 对象 'sys.sysprufiles' 的 1 页中有 2 行。 sys.sysftinds的 DBCC 结果。 对象 'sys.sysftinds' 的 0 页中有 0 行。 sys.sysowners的 DBCC 结果。 对象 'sys.sysowners' 的 1 页中有 14 行。 sys.sysdbreg的 DBCC 结果。 对象 'sys.sysdbreg' 的 0 页中有 0 行。 sys.sysprivs的 DBCC 结果。 对象 'sys.sysprivs' 的 1 页中有 139 行。 sys.sysschobjs的 DBCC 结果。 对象 'sys.sysschobjs' 的 34 页中有 2190 行。 sys.syscolpars的 DBCC 结果。 对象 'sys.syscolpars' 的 11 页中有 711 行。 sys.sysxlgns的 DBCC 结果。 对象 'sys.sysxlgns' 的 0 页中有 0 行。 sys.sysxsrvs的 DBCC 结果。 对象 'sys.sysxsrvs' 的 0 页中有 0 行。 sys.sysnsobjs的 DBCC 结果。 对象 'sys.sysnsobjs' 的 1 页中有 1 行。 sys.sysusermsgs的 DBCC 结果。 对象 'sys.sysusermsgs' 的 0 页中有 0 行。 sys.syscerts的 DBCC 结果。 对象 'sys.syscerts' 的 0 页中有 0 行。 sys.sysrmtlgns的 DBCC 结果。 对象 'sys.sysrmtlgns' 的 0 页中有 0 行。 sys.syslnklgns的 DBCC 结果。 对象 'sys.syslnklgns' 的 0 页中有 0 行。 sys.sysxprops的 DBCC 结果。 对象 'sys.sysxprops' 的 0 页中有 0 行。 sys.sysscalartypes的 DBCC 结果。 对象 'sys.sysscalartypes' 的 1 页中有 34 行。 sys.systypedsubobjs的 DBCC 结果。 对象 'sys.systypedsubobjs' 的 0 页中有 0 行。 sys.sysidxstats的 DBCC 结果。 对象 'sys.sysidxstats' 的 2 页中有 176 行。 sys.sysiscols的 DBCC 结果。 对象 'sys.sysiscols' 的 2 页中有 368 行。 sys.sysendpts的 DBCC 结果。 对象 'sys.sysendpts' 的 0 页中有 0 行。 sys.syswebmethods的 DBCC 结果。 对象 'sys.syswebmethods' 的 0 页中有 0 行。 sys.sysbinobjs的 DBCC 结果。 对象 'sys.sysbinobjs' 的 1 页中有 23 行。 sys.sysaudacts的 DBCC 结果。 对象 'sys.sysaudacts' 的 0 页中有 0 行。 sys.sysobjvalues的 DBCC 结果。 对象 'sys.sysobjvalues' 的 18 页中有 182 行。 sys.syscscolsegments的 DBCC 结果。 对象 'sys.syscscolsegments' 的 0 页中有 0 行。 sys.syscsdictionaries的 DBCC 结果。 对象 'sys.syscsdictionaries' 的 0 页中有 0 行。 sys.sysclsobjs的 DBCC 结果。 对象 'sys.sysclsobjs' 的 1 页中有 16 行。 sys.sysrowsetrefs的 DBCC 结果。 对象 'sys.sysrowsetrefs' 的 0 页中有 0 行。 sys.sysremsvcbinds的 DBCC 结果。 对象 'sys.sysremsvcbinds' 的 0 页中有 0 行。 sys.sysxmitqueue的 DBCC 结果。 对象 'sys.sysxmitqueue' 的 0 页中有 0 行。 sys.sysrts的 DBCC 结果。 对象 'sys.sysrts' 的 1 页中有 1 行。 sys.sysconvgroup的 DBCC 结果。 对象 'sys.sysconvgroup' 的 0 页中有 0 行。 sys.sysdesend的 DBCC 结果。 对象 'sys.sysdesend' 的 0 页中有 0 行。 sys.sysdercv的 DBCC 结果。 对象 'sys.sysdercv' 的 0 页中有 0 行。 sys.syssingleobjrefs的 DBCC 结果。 对象 'sys.syssingleobjrefs' 的 1 页中有 159 行。 sys.sysmultiobjrefs的 DBCC 结果。 对象 'sys.sysmultiobjrefs' 的 1 页中有 107 行。 sys.sysguidrefs的 DBCC 结果。 对象 'sys.sysguidrefs' 的 0 页中有 0 行。 sys.sysfoqueues的 DBCC 结果。 对象 'sys.sysfoqueues' 的 0 页中有 0 行。 sys.syschildinsts的 DBCC 结果。 对象 'sys.syschildinsts' 的 0 页中有 0 行。 sys.syscompfragments的 DBCC 结果。 对象 'sys.syscompfragments' 的 0 页中有 0 行。 sys.sysftsemanticsdb的 DBCC 结果。 对象 'sys.sysftsemanticsdb' 的 0 页中有 0 行。 sys.sysftstops的 DBCC 结果。 对象 'sys.sysftstops' 的 0 页中有 0 行。 sys.sysftproperties的 DBCC 结果。 对象 'sys.sysftproperties' 的 0 页中有 0 行。 sys.sysxmitbody的 DBCC 结果。 对象 'sys.sysxmitbody' 的 0 页中有 0 行。 sys.sysfos的 DBCC 结果。 对象 'sys.sysfos' 的 0 页中有 0 行。 sys.sysqnames的 DBCC 结果。 对象 'sys.sysqnames' 的 1 页中有 98 行。 sys.sysxmlcomponent的 DBCC 结果。 对象 'sys.sysxmlcomponent' 的 1 页中有 100 行。 sys.sysxmlfacet的 DBCC 结果。 对象 'sys.sysxmlfacet' 的 1 页中有 112 行。 sys.sysxmlplacement的 DBCC 结果。 对象 'sys.sysxmlplacement' 的 1 页中有 19 行。 sys.sysobjkeycrypts的 DBCC 结果。 对象 'sys.sysobjkeycrypts' 的 0 页中有 0 行。 sys.sysasymkeys的 DBCC 结果。 对象 'sys.sysasymkeys' 的 0 页中有 0 行。 sys.syssqlguides的 DBCC 结果。 对象 'sys.syssqlguides' 的 0 页中有 0 行。 sys.sysbinsubobjs的 DBCC 结果。 对象 'sys.sysbinsubobjs' 的 1 页中有 3 行。 sys.syssoftobjrefs的 DBCC 结果。 对象 'sys.syssoftobjrefs' 的 0 页中有 0 行。 sys.service_broker_map的 DBCC 结果。 对象 'sys.service_broker_map' 的 1 页中有 15 行。 sys.fulltext_thesaurus_metadata_table的 DBCC 结果。 对象 'sys.fulltext_thesaurus_metadata_table' 的 0 页中有 0 行。 sys.fulltext_thesaurus_state_table的 DBCC 结果。 对象 'sys.fulltext_thesaurus_state_table' 的 0 页中有 0 行。 sys.fulltext_thesaurus_phrase_table的 DBCC 结果。 对象 'sys.fulltext_thesaurus_phrase_table' 的 0 页中有 0 行。 sys.queue_messages_1977058079的 DBCC 结果。 对象 'sys.queue_messages_1977058079' 的 0 页中有 0 行。 sys.queue_messages_2009058193的 DBCC 结果。 对象 'sys.queue_messages_2009058193' 的 0 页中有 0 行。 sys.queue_messages_2041058307的 DBCC 结果。 对象 'sys.queue_messages_2041058307' 的 0 页中有 0 行。 sys.filestream_tombstone_2073058421的 DBCC 结果。 对象 'sys.filestream_tombstone_2073058421' 的 0 页中有 0 行。 sys.syscommittab的 DBCC 结果。 对象 'sys.syscommittab' 的 0 页中有 0 行。 sys.filetable_updates_2105058535的 DBCC 结果。 对象 'sys.filetable_updates_2105058535' 的 0 页中有 0 行。 CHECKDB 在数据库 'tempdb' 中发现 0 个分配错误和 0 个一致性错误。 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
DBCC CHECKDB([tempdb])会在每一个他所检查的表上获得一个共享表说 shared table
DBCC CHECKDB([tempdb])会跳过所有的分配和目录检查
ALTER DATABASE [tempdb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE DBCC CHECKDB([tempdb],REPAIR_ALLOW_DATA_LOSS) 消息 5058,级别 16,状态 4,第 1 行 在数据库 'tempdb' 中无法设置选项 'SINGLE_USER'。
tempdb无法修复
在tempdb中有3种类型的对象:用户对象,内部对象,版本库(sql2005引入)
f
f
进行排序操作时候会创建排序单元
除了order by用到排序,建立索引的时候也会用到排序
f
创建索引时有一个选项允许我们选择是在用户库中排序还是在tempdb中排序
CREATE INDEX ix_aa ON [dbo].[aaa] ([a]) WITH (SORT_IN_TEMPDB=ON)
当一个客户端应用程序调用了多个活动结果集MARS(multi active result sets)时
f
tempdb的事务日志只记录update前的旧值
sql2005还有一套更有效的搜索算法用来从混合区中找出单个可用页面
f
f
tempdb会缓存用户表,如果对该表进行了DDL操作,例如建索引,或者该表是动态sql创建的,那么对该表不会进行任何缓存
对大表删除操作实际上延迟删除操作,实际上每个数据库都是以延迟删除操作来改善整体吞吐量
延迟删除操作在tempdb中的改善最大
SELECT * FROM sys.[allocation_units]
查看type列和container_id列也是0值
type表示对象已经被删除
container_id分配空间不属于任何对象
TempDB--临时表的缓存 高文佳
--http://www.cnblogs.com/TeyGao/p/3817803.html
tempdb的数据文件数建议就是每个cpu对应一个文件
宋沄剑如何查看某个查询用了多少TempDB空间
http://www.cnblogs.com/CareySon/p/3910337.html
DECLARE @read BIGINT, @write BIGINT ; SELECT @read = SUM(num_of_bytes_read), @write = SUM(num_of_bytes_written) FROM tempdb.sys.database_files AS DBF JOIN sys.dm_io_virtual_file_stats(2, NULL) AS FS ON FS.file_id = DBF.file_id WHERE DBF.type_desc = 'ROWS' --这里放入需要测量的语句 SELECT tempdb_read_MB = (SUM(num_of_bytes_read) - @read) / 1024. / 1024., tempdb_write_MB = (SUM(num_of_bytes_written) - @write) / 1024. / 1024., internal_use_MB = ( SELECT internal_objects_alloc_page_count / 128.0 FROM sys.dm_db_task_space_usage WHERE session_id = @@SPID ) FROM tempdb.sys.database_files AS DBF JOIN sys.dm_io_virtual_file_stats(2, NULL) AS FS ON FS.file_id = DBF.file_id WHERE DBF.type_desc = 'ROWS'
f
最好不要对tempdb进行收缩,如果任何内部对象或版本存储区页面需要移动,那么是不能收缩这些文件
优化建议
利用tempdb的对象缓存
保持事务短小,特别是使用了快照隔离级别,mars或触发器事务
f
SELECT * FROM sys.[dm_db_file_space_usage]
tempdb空间监视
f
三个视图都有共同特征,结尾都有:space_usage
--[dm_db_file_space_usage]系统视图能够显示三种类型的存储是怎样使用的 SELECT * FROM sys.[dm_db_file_space_usage] --[dm_db_task_space_usage]视图为每一个活动的任务返回一行并显示该任务 --为用户对象和内部对象所分配和释放的空间。如果一个会话没有运行任何任务 --该视图会为这个会话返回一行信息,其中所有的空间信息值都为0 --因为版本存储区空间与任何特定的任务或会话都没有关联,所以该视图给出的信息中 --没有版本存储区信息 SELECT * FROM sys.[dm_db_task_space_usage] --[dm_db_session_space_usage]视图为每一个会话返回一行,返回的信息中 --包含有该会话为用户对象和内部对象,以及所有已经完成的任务所分配的空间 --和释放空间的累计值。一般来讲,分配的空间值应该与释放的空间值相同 --不过,如果含有延迟的删除操作,那么分配出的值会比释放的值要大。需要注意 --不是所有的用户都能看到这些信息,需要有view server state 权限才能查询该视图 SELECT * FROM sys.[dm_db_session_space_usage]
--这里放入需要测量的语句 --[dm_db_task_space_usage]视图为每一个活动的任务返回一行并显示该任务 --为用户对象和内部对象所分配和释放的空间。如果一个会话没有运行任何任务 --该视图会为这个会话返回一行信息,其中所有的空间信息值都为0 --因为版本存储区空间与任何特定的任务或会话都没有关联,所以该视图给出的信息中 --没有版本存储区信息 --SELECT * FROM sys.[dm_db_task_space_usage] SELECT tempdb_read_MB = (SUM(num_of_bytes_read) - @read) / 1024. / 1024., tempdb_write_MB = (SUM(num_of_bytes_written) - @write) / 1024. / 1024., internal_use_MB = ( SELECT internal_objects_alloc_page_count / 128.0 FROM sys.dm_db_task_space_usage WHERE session_id = @@SPID ) FROM tempdb.sys.database_files AS DBF JOIN sys.dm_io_virtual_file_stats(2, NULL) AS FS ON FS.file_id = DBF.file_id WHERE DBF.type_desc = 'ROWS'
f
sqlserver安全
sqlserver安全模型包含两部分:1验证和2授权
f
一级主体代表一个用户,例如一个sqlserver或Windows登录帐户
二级主体代表多个用户 ,例如一个角色或一个Windows用户组
f
f
f
f
f
f
f
一级主体代表一个用户,例如一个sqlserver或Windows登录帐户
二级主体代表多个用户 ,例如一个角色或一个Windows用户组
f
默认架构sys 提供了一种访问系统表和系统视图的方法
访问顺序是1先找sys.table1,2找sueschema.table1,3找dbo.mytable1
f
f
f
分离数据库可以使用single_user模式回滚事务,保证没有脏页
drop database并不会检查脏数据页和活动事务
附加数据库时最好使用create database而不要使用sp_attach_db
sp_attach_db正在被淘汰,sp_attach_db的限制是16个文件,而create database没有这个限制
而我们使用GUI生成脚本的时候也是使用create database
USE [master] GO CREATE DATABASE [sss] ON ( FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\sss.mdf' ), ( FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\sss_log.ldf' ) FOR ATTACH GO
f
f
重建日志文件
USE [master] GO CREATE DATABASE [sss] ON ( FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\sss.mdf' ), ( FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\sss_log.ldf' ) FOR ATTACH_REBUILD_LOG GO
FOR ATTACH_REBUILD_LOG会截断日志链!!所以执行之前最后完备数据库
f
f
SELECT [name],[physical_name] AS currentlocation,[state_desc] FROM sys.[master_files] WHERE [database_id]=DB_ID('dbname')
移动系统数据库
master-only
最小配置启动 /f 实际上叫master-only 模式
--默认实例
net start MSSQLSERVER /f /T3608
--命名实例
net start MSSQL$instancename /f /T3608
f
如果移动master数据库那么也必须移动resource数据库
f
使用配置管理器去移动数据库文件的方法
f
注意移动resource数据库后我们不能使用系统视图来查看resource数据库的路径!!
f
兼容性级别
兼容性级别可以改为90、80、70、65、60
兼容性级别65和60正在被淘汰
f
兼容性级别只影响是否识别新的关键字和新的语法,并且他们并不影响对一个查询的内部处理
,例如当改变兼容级别为80时,我们并不能使系统表可见或摆脱架构,而pivot是sql2005中的一个新的关键字,我们可以通过设置兼容级别为80来创建名为pivot的表而不用使用任何分隔符
f
第五章 日志和恢复
f
缓存管理器,日志记录进去缓存管理器
只有数据页的lsn小于或等于最后写入日志的数据页的lsn时,脏页才可能写入磁盘
f
SAVE TRAN事务用到保存点也会记录到事务日志
f
补偿日志记录
f
崩溃恢复 crash recovery
clean shutdown
重启恢复可以在多个数据库上并行运行,每个数据库的恢复都有一个不同的线程来进行
f
发生更改的数据页是完全异步地写入磁盘上的数据文件
先redo再undo
f
恢复的各个截断
recovery的各个阶段
恢复算法
f
和inside sqlserver2000的内容和图片一样
http://www.cnblogs.com/lyhabc/p/3460272.html
f
sqlserver企业版和开发版支持快速恢复
页面LSN不能介于日志项之前和当前LSN的值之间
即 之前lsn<页面lsn<当前lsn
sqlserver都不知道怎么做了
之前lsn<页面lsn 有可能要回滚
页面lsn<当前lsn 有可能要重做
那么究竟重做还是回滚??所以页面LSN不能介于日志项之前和当前LSN的值之间!!
f
f
截断事务日志是一种逻辑操作而不是一种物理操作,他仅仅标记部分日志为失效从而运行那些空间重新被使用,他不会减少磁盘上事务日志文件的大小,为了缩小物理文件大小,必须进行收缩操作
f
虚拟日志文件,一个0.5mb的日志文件含有两个vlf(一个vlf的最小大小是31*8kb =0.2mb)
一个vlf的最小大小是0.2MB
8KB怀疑就是一个数据页
namespace InternalsViewer.Internals.TransactionLog
Log Data containing fragment of a page at a particular offset
Log Block顺序号(4字节)
Log Block内的顺序编号(2字节)
f
f
F
tempdb的dbcc loginfo
F
dbcc loginfo中第一个vlf在8192字节之后开始,这正是一个数据页所包含的字节数目
日志文件的第一个物理页包含的是页头信息而不是日志记录,所以可以认为VLF从第二页开始
文件大小filesize列对大多数结果行实际上都是冗余的,因为文件大小可以通过减去两个后续VLF的起点偏移计算出来.这些行按照物理顺序列出,但并不总是与VLF的实际使用顺序一致.
使用顺序(逻辑顺序)反映在FSeqNo列(代表文件序列号)上.
FSeqNo:虚拟日志文件序列号
这些vlf以物理顺序startoffset顺序列出,但是逻辑顺序并不匹配,文件序列号的值显示按照使用(逻辑)顺序的首个vlf实际上是第七个vlf 4989,按照使用顺序的最后一个vlf实际上是按照物理顺序的第五个vlf4998
f
没有必要设置多个事务日志文件,因为是顺序流
虚拟日志文件的截断vlf
f
在sp_configure里恢复间隔默认显示为0,意味着sqlserver将会自动调节该值,sqlserver恢复间隔的取值是基于这样的估计,那就是10MB的事务能够在1分钟内恢复
实际的日志截断被checkpoint过程所调用,checkpoint过程通常处于休眠状态,只是在需要的时候才被唤醒。每当一个用户线程调用日志管理器,日志管理器都会检查日志的大小。如果日志的大小超出了sqlserver在恢复间隔内能够恢复的工作量,那么checkpoint线程就会被唤醒,checkpoint线程对数据库执行checkpoint操作,然后截断日志中不活动部分
f
另外如果日志缓存区使用达到70%,那么日志管理器会唤醒checkpoint线程并强行做一次checkpoint操作,因为扩张日志的代价远远大于截断日志的代价,所以sqlserver只要有可能就会选择截断日志
如果日志管理器从未被调用,那么checkpoint也不会被调用,从而截断也不会发生!!
f
--[last_log_backup_lsn]如果为null就是自动截断模式 --从来没有进行过完整备份会一直自动截断 SELECT DB_NAME([database_id]) AS 'dbname',* FROM sys.[database_recovery_status]
f
f
DBCC SHRINKFILE (N'sss_log' , 1)
sqlserver会在日志中标记一个压缩点(收缩日志),直到日志记录由于日志的备份或截断被清空后才会进行实际的收缩操作
在sqlserver7.0的时候首次引入这样的日志结构,精确地按照如上语句运行并不一定会收缩物理日志文件,当日志文件不收缩时是因为日志的活动部分处于物理文件的尾端
在sqlserver2000和sqlserver2005中已经没有必要这么做了,如果收缩命令已经执行过了,那么之后截断日志时会在内部产生一系列“空操作”(或者称为”哑元“)日志记录以保证活动日志记录从文件尾端移走,一旦日志不再需要时,收缩操作就会立刻发生
收缩数据文件也是从尾端开始移动页面
如果数据库设置了自动收缩选项,那么一个自动收缩进程会每隔30分钟触发一次并且决定这个日志收缩的大小,在两次收缩间隔内,日志管理器会累计30分钟内已使用的最大日志空间的统计数值。
f
DBCC SQLPERF(LOGSPACE)
f
事务日志毕竟不是用来作为审计的工具
Lumigent公司的log explorer 工具读取事务日志
通过一个无文档说明的DBCC命令来读取日志记录
他们花费了数以万计小时查看字节级别的日志文件的dump并且将此信息与那个无文档说明的DBCC命令关联起来
f
f
完备的时候获取current lsn
sql2005也支持称为日志标识(log marks)的特性,允许我们在事务日志中放置一些参考点
f
sql2005中的每一个数据文件都至少有一个称为大批量更改位图的页面BCM
一个BCM页面的所有位会在每次日志备份发生时被重置为0
差异备份或者大容量日志bulk_logged模式下,为什么备份文件会比完备大的原因
日志备份时,sqlserver会扫描BCM页面并在备份事务日志自身的同时备份所有修改过的区。日志文件自身会保持很小,但是该日志的备份可能会比日志文件大上很多倍。所以日志备份需要更多时间并且可能会比完整模式消耗更多空间
还原一个在大容量日志模式所做的日志备份消耗的时间和还原一个在完整模式下所做的日志备份所用的时间基本相同(一般来说还原完整备份的时间会长一些),还原过程不需要重做各个操作(redo,undo),恢复所有的数据和索引结构所需的信息都包含在日志备份中
使用大容量日志模式,实际上就是把数据放入日志备份的bak中,日志备份的bak基本没有大容量操作的log!!!
所以无论是备份还是还原,所用的时间都比完整长,还原可能跟完整差不多!!
f
微软在sqlserver2000引入了这3个恢复模型
并用他们来取代
select into/bulkcopy
trunc.log on chkpt数据库选项 (sql6.5有这些选项)
在sql2000和sql2005下使用sp_dboption改变这些选项也会改变恢复模型,同时改变恢复模型也会改变这些选项的一到两项的值
SQL Server 2008如何压缩日志(log)文件?
http://www.cnblogs.com/downmoon/archive/2009/12/13/1623004.html
use DB_NAME sp_dboption DB_NAME, "trunc. log on chkpt.", true checkpoint sp_dboption DB_NAME, "autoshrink", true
f
在sql2000时一旦执行了select into 或批量复制bulk copy ,我们就不能再备份事务日志了,但在sql2005就可以
f
f
备份尾日志
这相当于指定以下 BACKUPTransact-SQL 语句: BACKUP LOG database_name TO <backup_device> WITH NORECOVERY
还原文件和文件组之后应用日志备份,并且在简单模式下无法进行日志备份,所以有readwrite属性的单个文件或文件组只有在完整或大容量日志模式下才能进行备份
f
在还原单个文件或文件组之前瞬间,我们必须备份事务日志,我们必须拥有从文件或文件组备份创建时开始的完整备份日志链
在还原一个文件或文件组的备份之后,我们必须还原备份文件或文件组时间点和还原他们的时间点之间的所有事务日志,这确保了被还原的文件和数据库其余部分的同步
段落还原 ,文件组还原,文件还原
with no_truncate选项来进行备份尾日志,但是我们也能使用NORECOVERY选项
数据库三大会议之一的VLDB(Very Large Data Base)即将于9月1日到5日在杭州召开,会议地点位于美丽西湖旁边的黄龙酒店。这是该会议第一次由中国大陆承办,届时将有全世界知名的数据库领域学者和专家进行学术报告,请大家不要错过这次宝贵的交流机会。目前会议注册网站已经开放
http://www.vldb.org/2014/registration.html
f
损坏的页面能够在下面活动时探测到
1某个查询需要读取一个数据页
2DBCC CHECKDB或DBCC CHECKTABLE开始运行时
3BACKUP 或RESTORE数据库开始运行时
4数据库被删除时
5使用DBCC DBREPAIR修复数据库时
http://www.cnblogs.com/lyhabc/articles/3740063.html
suspect_pages 表中记录的错误
在 suspect_pages 表中,由于出现 824 错误而失败的每页占一行,最多为 1,000 行。 下表显示了记录在 suspect_pages 表的 event_type 列中的错误。
错误说明 |
event_type 值 |
---|---|
由操作系统 CRC 错误造成的 823 错误,或者校验和错误或页撕裂以外的 824 错误(例如,页 ID 错误) |
1 |
错误的校验和 |
2 |
残缺页 |
3 |
已还原(页在标记为错误后已还原) |
4 |
已修复(DBCC 修复了页) |
5 |
已由 DBCC 释放 |
7 |
暂时性的错误也会记录在 suspect_pages 表中。 暂时性错误的来源包含 I/O 错误(例如电缆断开连接)或暂时未通过重复校验和测试的页。
f
并不是所有损坏的数据页面都能够在数据库联机的情况下进行还原
只有sql2005企业版允许进行联机还原
从包含损坏页面的完整或文件或文件组备份中开始还原页面
在单个文件中可被还原的最大页面数目是1000!!
从suspect_pages表中获取损坏页面的页面ID,然后进行页面还原!!
SELECT [redo_target_lsn],DB_NAME([database_id]) AS dbname,* FROM sys.[master_files] WHERE [database_id]=19
[redo_target_lsn]
创建一个日志备份,他包括被还原页面的last lsn,也就是当最后还原的页面进入离线时的那一点,last lsn(作为序列中首先还原的一部分)就是重做操作的目标lsn
查看sys.[master_files]表的[redo_target_lsn]列来了解当前重做操作的目标lsn
f
sqlserver的standby的选项,他允许我们恢复数据库并能继续还原更多的日志备份
如果我们在还原一个数据库时指定with standby='<some filename>'
sqlserver会回滚不完整的事务并在指定的文件中跟踪那些被回滚的工作,那些指定的文件被称为备用文件(standby file)。下一次的还原操作会读取备用文件中的内容并重做回滚的操作,然后才还原下一个日志备份。如果接下来的还原也指定了with standby,不完整的事务会被再次回滚,但那些被回滚的事务的记录会被保存。需要注意的是如果使用了with standby 还原,我们就不能修改任何数据(如果尝试去修改的话,sqlserver会报错),不过我们可以读取数据并继续还原更多的日志,为了使数据库完全可用,最后的日志必须使用with recovery来还原(并且不会保存任何备用文件)!!
博客园团队迁移数据库到云上的时候使用了standby选项
http://www.cnblogs.com/cmt/archive/2013/02/25/aliyun-database-migrate.html
云计算之路:数据库迁移方案
f
f
第六章 表
表中的每一个数据实例表现为单个实体,或者叫行(正式名称叫元祖)
f
系统基本表有时也被称为系统目录(system catalog)
f
兼容性视图创建在隐藏在资源数据库中
f
像syssegments ,段其作用仅仅是为了支持向后兼容性,我觉得应该已经没有段的概念
兼容性视图不包括sql2005的新功能,例如表分区
sql2005还为sql2000的伪表pseudo-tables提供兼容性视图,像sysprocess以及sysccacheobjects,伪表的数据不是预先存储在磁盘上的,而是需要的时候从内部结构来构建
目录视图跟兼容性视图是有区别
目录视图:sys.objects
兼容性视图:sys.sysobjects
目录视图的列和兼容性视图的列可能不一样
f
目录视图以继承模型构建,从而避免了内部重复定义许多对象的通用的属性组
f
infomation schema view 信息架构视图是从sqlserver7.0开始引入的独立于系统表的原始视图
写一个可移植程序来访问元数据的话,应该考虑使用信息架构视图
f
f
元数据层次
f
f
f
f
f
数据类型
f
日期时间类型
f
f
f
sqlserver不支持任何无符号的int/smallint数据类型,所以int类型最大只能到21亿
f
sqlserver不支持任何无符号的int/smallint数据类型,所以int类型最大只能到21亿!!
f
f
uniqueidentifier数据类型有时被称为GUID(GLOBALLY UNIQUE IDENTIFIER)或UUID(UNIVERSAL UNIQUE IDENTIFIER) GUID或UUID是一个以这种方式生成的128位(16字节)值出于实际目的考虑,保证值在全球范围内的唯一性,即使对未接入网络的计算机也是如此,GUIID正成为分布式系统的一种重要手段
mysql 中的uuid生成
USE test; CREATE TABLE `uuidtest_inno` ( `id` char(36) CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 insert into uuidtest_inno value(uuid()); SELECT * FROM uuidtest_inno
SELECT NEWSEQUENTIALID()
UNIQUEIDENTIFIER的最后六个字节组成了该机器的节点号。如果该sqlserver主机没有以太网地址就没有节点号,这样生成的GUID只能保证在该机器产生的GUID中是唯一的
在有网络地址的计算机上产生的GUID才能保证是全球唯一的
guid主要是为了合并复制中使用,所以在合并复制的表中会多了一个guid列
NEWSEQUENTIALID()函数是对Windows函数UuidCreateSequential进行了封装,进行了一些字节混序并创建了一种产生UUID值的顺序
f
可能的话,我们建议将所有的列设置为not null
f
f
--查看当前系统中所有连接的会话选项值 SELECT * FROM sys.[dm_exec_sessions]
f
f
f
自增值
使用bcp的时候使用-E(大写)参数来保留identity的值
bulkinsert的keepidentity选项
f
f
f
sqlserver在重启的时候会恢复正确的标识值,sqlserver在做checkpoint的时候通过将所有表的当前的标识值刷到表中来达到此目的,对于上次checkpoint之前的活动,在标准的数据库恢复过程中会将后面的值从事务日志中重建
内部存储,系统目录视图,系统表
f
sys.tables
包含列
表名,对象id,表所属的架构id
sys.tables继承了sys.objects的所有列并且还包含了表对象特有的列
sys.columns
包含列
列名,数据类型,长度,列id
information_schema信息架构视图保存了一个称为ordinal_position的值,当删除一列的时候,信息架构视图还会保存着位置
f
sys.indexes
sys.partitions
sys.allocation_units
sys.system_internals_allocation_units
由于单张表最多只可以有249个非聚集索引,并且对于heap或聚集索引各有一条记录,那么每张表在sys.indexes视图中都有1~250条记录,
表还可以有XML索引,XML索引的元数据通过sys.xml_indexes目录视图(继承自sys.indexes视图的列)得到
f
sys.[indexes]和sys.[partitions]之间是一对多的关系
一个表最多可以有1000个分区,默认至少有一个分区sys.[partitions]
SELECT *
FROM sys.[indexes] AS indexs
INNER JOIN sys.[partitions] AS parti ON [parti].[object_id] = [indexs].[object_id]
ORDER BY [indexs].[object_id]
f
f
SELECT * FROM sys.[indexes] AS indexs INNER JOIN sys.[partitions] AS parti ON [parti].[object_id] = [indexs].[object_id] AND [parti].[index_id] = [indexs].[index_id] INNER JOIN [sys].[system_internals_allocation_units] AS allo ON allo.[container_id]=[parti].[partition_id] ORDER BY [indexs].[object_id]
f
f
每条offset table中的记录对应一个2字节项 对应页面中的一条记录
f
f
f
f
行偏移表
位类型bit
m_slotCnt = 700
为什麽只能容纳700行数据
2状态A+状态B+2定长数据的大小+1定长数据内容+2列数量+1null位图=8字节
8字节*700行=5.6kb 数据内容
700行*2字节=1.4kb 行偏移矩阵
5.6+1.4=7kb 差不多一个数据页
按照力伟文章的解释:
http://www.cnblogs.com/stswordman/archive/2007/08/22/865425.html
9字节*700行=6.3kb 数据内容
700行*2字节=1.4kb 行偏移矩阵
6.3+1.4=7.7kb 差不多一个数据页
数据行
000000000D3ABFF0: ad00a200 97008c00 81007600 6b006000 †..
USE [sss] CREATE TABLE testrow(id BIT DEFAULT 1) CREATE TABLE DBCCResult ( PageFID NVARCHAR(200), PagePID NVARCHAR(200), IAMFID NVARCHAR(200), IAMPID NVARCHAR(200), ObjectID NVARCHAR(200), IndexID NVARCHAR(200), PartitionNumber NVARCHAR(200), PartitionID NVARCHAR(200), iam_chain_type NVARCHAR(200), PageType NVARCHAR(200), IndexLevel NVARCHAR(200), NextPageFID NVARCHAR(200), NextPagePID NVARCHAR(200), PrevPageFID NVARCHAR(200), PrevPagePID NVARCHAR(200) ) INSERT INTO testrow DEFAULT VALUES GO 10000 INSERT INTO DBCCResult EXEC ('DBCC IND(sss,testrow,-1) ') SELECT * FROM [dbo].[testrow] SELECT * FROM [dbo].[DBCCResult] DBCC TRACEON(3604,-1) GO DBCC PAGE([sss],1,214,2) GO
OFFSET TABLE: Row - Offset 699 (0x2bb) - 6387 (0x18f3) 698 (0x2ba) - 6378 (0x18ea) 697 (0x2b9) - 6369 (0x18e1) 696 (0x2b8) - 6360 (0x18d8) 695 (0x2b7) - 6351 (0x18cf) 694 (0x2b6) - 6342 (0x18c6) 693 (0x2b5) - 6333 (0x18bd) 692 (0x2b4) - 6324 (0x18b4) 691 (0x2b3) - 6315 (0x18ab) 690 (0x2b2) - 6306 (0x18a2) 689 (0x2b1) - 6297 (0x1899) 688 (0x2b0) - 6288 (0x1890) 687 (0x2af) - 6279 (0x1887) 686 (0x2ae) - 6270 (0x187e) 685 (0x2ad) - 6261 (0x1875) 684 (0x2ac) - 6252 (0x186c) 683 (0x2ab) - 6243 (0x1863) 682 (0x2aa) - 6234 (0x185a) 681 (0x2a9) - 6225 (0x1851) 680 (0x2a8) - 6216 (0x1848) 679 (0x2a7) - 6207 (0x183f) 678 (0x2a6) - 6198 (0x1836) 677 (0x2a5) - 6189 (0x182d) 676 (0x2a4) - 6180 (0x1824) 675 (0x2a3) - 6171 (0x181b) 674 (0x2a2) - 6162 (0x1812) 673 (0x2a1) - 6153 (0x1809) 672 (0x2a0) - 6144 (0x1800) 671 (0x29f) - 6135 (0x17f7) 670 (0x29e) - 6126 (0x17ee) 669 (0x29d) - 6117 (0x17e5) 668 (0x29c) - 6108 (0x17dc) 667 (0x29b) - 6099 (0x17d3) 666 (0x29a) - 6090 (0x17ca) 665 (0x299) - 6081 (0x17c1) 664 (0x298) - 6072 (0x17b8) 663 (0x297) - 6063 (0x17af) 662 (0x296) - 6054 (0x17a6) 661 (0x295) - 6045 (0x179d) 660 (0x294) - 6036 (0x1794) 659 (0x293) - 6027 (0x178b) 658 (0x292) - 6018 (0x1782) 657 (0x291) - 6009 (0x1779) 656 (0x290) - 6000 (0x1770) 655 (0x28f) - 5991 (0x1767) 654 (0x28e) - 5982 (0x175e) 653 (0x28d) - 5973 (0x1755) 652 (0x28c) - 5964 (0x174c) 651 (0x28b) - 5955 (0x1743) 650 (0x28a) - 5946 (0x173a) 649 (0x289) - 5937 (0x1731) 648 (0x288) - 5928 (0x1728) 647 (0x287) - 5919 (0x171f) 646 (0x286) - 5910 (0x1716) 645 (0x285) - 5901 (0x170d) 644 (0x284) - 5892 (0x1704) 643 (0x283) - 5883 (0x16fb) 642 (0x282) - 5874 (0x16f2) 641 (0x281) - 5865 (0x16e9) 640 (0x280) - 5856 (0x16e0) 639 (0x27f) - 5847 (0x16d7) 638 (0x27e) - 5838 (0x16ce) 637 (0x27d) - 5829 (0x16c5) 636 (0x27c) - 5820 (0x16bc) 635 (0x27b) - 5811 (0x16b3) 634 (0x27a) - 5802 (0x16aa) 633 (0x279) - 5793 (0x16a1) 632 (0x278) - 5784 (0x1698) 631 (0x277) - 5775 (0x168f) 630 (0x276) - 5766 (0x1686) 629 (0x275) - 5757 (0x167d) 628 (0x274) - 5748 (0x1674) 627 (0x273) - 5739 (0x166b) 626 (0x272) - 5730 (0x1662) 625 (0x271) - 5721 (0x1659) 624 (0x270) - 5712 (0x1650) 623 (0x26f) - 5703 (0x1647) 622 (0x26e) - 5694 (0x163e) 621 (0x26d) - 5685 (0x1635) 620 (0x26c) - 5676 (0x162c) 619 (0x26b) - 5667 (0x1623) 618 (0x26a) - 5658 (0x161a) 617 (0x269) - 5649 (0x1611) 616 (0x268) - 5640 (0x1608) 615 (0x267) - 5631 (0x15ff) 614 (0x266) - 5622 (0x15f6) 613 (0x265) - 5613 (0x15ed) 612 (0x264) - 5604 (0x15e4) 611 (0x263) - 5595 (0x15db) 610 (0x262) - 5586 (0x15d2) 609 (0x261) - 5577 (0x15c9) 608 (0x260) - 5568 (0x15c0) 607 (0x25f) - 5559 (0x15b7) 606 (0x25e) - 5550 (0x15ae) 605 (0x25d) - 5541 (0x15a5) 604 (0x25c) - 5532 (0x159c) 603 (0x25b) - 5523 (0x1593) 602 (0x25a) - 5514 (0x158a) 601 (0x259) - 5505 (0x1581) 600 (0x258) - 5496 (0x1578) 599 (0x257) - 5487 (0x156f) 598 (0x256) - 5478 (0x1566) 597 (0x255) - 5469 (0x155d) 596 (0x254) - 5460 (0x1554) 595 (0x253) - 5451 (0x154b) 594 (0x252) - 5442 (0x1542) 593 (0x251) - 5433 (0x1539) 592 (0x250) - 5424 (0x1530) 591 (0x24f) - 5415 (0x1527) 590 (0x24e) - 5406 (0x151e) 589 (0x24d) - 5397 (0x1515) 588 (0x24c) - 5388 (0x150c) 587 (0x24b) - 5379 (0x1503) 586 (0x24a) - 5370 (0x14fa) 585 (0x249) - 5361 (0x14f1) 584 (0x248) - 5352 (0x14e8) 583 (0x247) - 5343 (0x14df) 582 (0x246) - 5334 (0x14d6) 581 (0x245) - 5325 (0x14cd) 580 (0x244) - 5316 (0x14c4) 579 (0x243) - 5307 (0x14bb) 578 (0x242) - 5298 (0x14b2) 577 (0x241) - 5289 (0x14a9) 576 (0x240) - 5280 (0x14a0) 575 (0x23f) - 5271 (0x1497) 574 (0x23e) - 5262 (0x148e) 573 (0x23d) - 5253 (0x1485) 572 (0x23c) - 5244 (0x147c) 571 (0x23b) - 5235 (0x1473) 570 (0x23a) - 5226 (0x146a) 569 (0x239) - 5217 (0x1461) 568 (0x238) - 5208 (0x1458) 567 (0x237) - 5199 (0x144f) 566 (0x236) - 5190 (0x1446) 565 (0x235) - 5181 (0x143d) 564 (0x234) - 5172 (0x1434) 563 (0x233) - 5163 (0x142b) 562 (0x232) - 5154 (0x1422) 561 (0x231) - 5145 (0x1419) 560 (0x230) - 5136 (0x1410) 559 (0x22f) - 5127 (0x1407) 558 (0x22e) - 5118 (0x13fe) 557 (0x22d) - 5109 (0x13f5) 556 (0x22c) - 5100 (0x13ec) 555 (0x22b) - 5091 (0x13e3) 554 (0x22a) - 5082 (0x13da) 553 (0x229) - 5073 (0x13d1) 552 (0x228) - 5064 (0x13c8) 551 (0x227) - 5055 (0x13bf) 550 (0x226) - 5046 (0x13b6) 549 (0x225) - 5037 (0x13ad) 548 (0x224) - 5028 (0x13a4) 547 (0x223) - 5019 (0x139b) 546 (0x222) - 5010 (0x1392) 545 (0x221) - 5001 (0x1389) 544 (0x220) - 4992 (0x1380) 543 (0x21f) - 4983 (0x1377) 542 (0x21e) - 4974 (0x136e) 541 (0x21d) - 4965 (0x1365) 540 (0x21c) - 4956 (0x135c) 539 (0x21b) - 4947 (0x1353) 538 (0x21a) - 4938 (0x134a) 537 (0x219) - 4929 (0x1341) 536 (0x218) - 4920 (0x1338) 535 (0x217) - 4911 (0x132f) 534 (0x216) - 4902 (0x1326) 533 (0x215) - 4893 (0x131d) 532 (0x214) - 4884 (0x1314) 531 (0x213) - 4875 (0x130b) 530 (0x212) - 4866 (0x1302) 529 (0x211) - 4857 (0x12f9) 528 (0x210) - 4848 (0x12f0) 527 (0x20f) - 4839 (0x12e7) 526 (0x20e) - 4830 (0x12de) 525 (0x20d) - 4821 (0x12d5) 524 (0x20c) - 4812 (0x12cc) 523 (0x20b) - 4803 (0x12c3) 522 (0x20a) - 4794 (0x12ba) 521 (0x209) - 4785 (0x12b1) 520 (0x208) - 4776 (0x12a8) 519 (0x207) - 4767 (0x129f) 518 (0x206) - 4758 (0x1296) 517 (0x205) - 4749 (0x128d) 516 (0x204) - 4740 (0x1284) 515 (0x203) - 4731 (0x127b) 514 (0x202) - 4722 (0x1272) 513 (0x201) - 4713 (0x1269) 512 (0x200) - 4704 (0x1260) 511 (0x1ff) - 4695 (0x1257) 510 (0x1fe) - 4686 (0x124e) 509 (0x1fd) - 4677 (0x1245) 508 (0x1fc) - 4668 (0x123c) 507 (0x1fb) - 4659 (0x1233) 506 (0x1fa) - 4650 (0x122a) 505 (0x1f9) - 4641 (0x1221) 504 (0x1f8) - 4632 (0x1218) 503 (0x1f7) - 4623 (0x120f) 502 (0x1f6) - 4614 (0x1206) 501 (0x1f5) - 4605 (0x11fd) 500 (0x1f4) - 4596 (0x11f4) 499 (0x1f3) - 4587 (0x11eb) 498 (0x1f2) - 4578 (0x11e2) 497 (0x1f1) - 4569 (0x11d9) 496 (0x1f0) - 4560 (0x11d0) 495 (0x1ef) - 4551 (0x11c7) 494 (0x1ee) - 4542 (0x11be) 493 (0x1ed) - 4533 (0x11b5) 492 (0x1ec) - 4524 (0x11ac) 491 (0x1eb) - 4515 (0x11a3) 490 (0x1ea) - 4506 (0x119a) 489 (0x1e9) - 4497 (0x1191) 488 (0x1e8) - 4488 (0x1188) 487 (0x1e7) - 4479 (0x117f) 486 (0x1e6) - 4470 (0x1176) 485 (0x1e5) - 4461 (0x116d) 484 (0x1e4) - 4452 (0x1164) 483 (0x1e3) - 4443 (0x115b) 482 (0x1e2) - 4434 (0x1152) 481 (0x1e1) - 4425 (0x1149) 480 (0x1e0) - 4416 (0x1140) 479 (0x1df) - 4407 (0x1137) 478 (0x1de) - 4398 (0x112e) 477 (0x1dd) - 4389 (0x1125) 476 (0x1dc) - 4380 (0x111c) 475 (0x1db) - 4371 (0x1113) 474 (0x1da) - 4362 (0x110a) 473 (0x1d9) - 4353 (0x1101) 472 (0x1d8) - 4344 (0x10f8) 471 (0x1d7) - 4335 (0x10ef) 470 (0x1d6) - 4326 (0x10e6) 469 (0x1d5) - 4317 (0x10dd) 468 (0x1d4) - 4308 (0x10d4) 467 (0x1d3) - 4299 (0x10cb) 466 (0x1d2) - 4290 (0x10c2) 465 (0x1d1) - 4281 (0x10b9) 464 (0x1d0) - 4272 (0x10b0) 463 (0x1cf) - 4263 (0x10a7) 462 (0x1ce) - 4254 (0x109e) 461 (0x1cd) - 4245 (0x1095) 460 (0x1cc) - 4236 (0x108c) 459 (0x1cb) - 4227 (0x1083) 458 (0x1ca) - 4218 (0x107a) 457 (0x1c9) - 4209 (0x1071) 456 (0x1c8) - 4200 (0x1068) 455 (0x1c7) - 4191 (0x105f) 454 (0x1c6) - 4182 (0x1056) 453 (0x1c5) - 4173 (0x104d) 452 (0x1c4) - 4164 (0x1044) 451 (0x1c3) - 4155 (0x103b) 450 (0x1c2) - 4146 (0x1032) 449 (0x1c1) - 4137 (0x1029) 448 (0x1c0) - 4128 (0x1020) 447 (0x1bf) - 4119 (0x1017) 446 (0x1be) - 4110 (0x100e) 445 (0x1bd) - 4101 (0x1005) 444 (0x1bc) - 4092 (0xffc) 443 (0x1bb) - 4083 (0xff3) 442 (0x1ba) - 4074 (0xfea) 441 (0x1b9) - 4065 (0xfe1) 440 (0x1b8) - 4056 (0xfd8) 439 (0x1b7) - 4047 (0xfcf) 438 (0x1b6) - 4038 (0xfc6) 437 (0x1b5) - 4029 (0xfbd) 436 (0x1b4) - 4020 (0xfb4) 435 (0x1b3) - 4011 (0xfab) 434 (0x1b2) - 4002 (0xfa2) 433 (0x1b1) - 3993 (0xf99) 432 (0x1b0) - 3984 (0xf90) 431 (0x1af) - 3975 (0xf87) 430 (0x1ae) - 3966 (0xf7e) 429 (0x1ad) - 3957 (0xf75) 428 (0x1ac) - 3948 (0xf6c) 427 (0x1ab) - 3939 (0xf63) 426 (0x1aa) - 3930 (0xf5a) 425 (0x1a9) - 3921 (0xf51) 424 (0x1a8) - 3912 (0xf48) 423 (0x1a7) - 3903 (0xf3f) 422 (0x1a6) - 3894 (0xf36) 421 (0x1a5) - 3885 (0xf2d) 420 (0x1a4) - 3876 (0xf24) 419 (0x1a3) - 3867 (0xf1b) 418 (0x1a2) - 3858 (0xf12) 417 (0x1a1) - 3849 (0xf09) 416 (0x1a0) - 3840 (0xf00) 415 (0x19f) - 3831 (0xef7) 414 (0x19e) - 3822 (0xeee) 413 (0x19d) - 3813 (0xee5) 412 (0x19c) - 3804 (0xedc) 411 (0x19b) - 3795 (0xed3) 410 (0x19a) - 3786 (0xeca) 409 (0x199) - 3777 (0xec1) 408 (0x198) - 3768 (0xeb8) 407 (0x197) - 3759 (0xeaf) 406 (0x196) - 3750 (0xea6) 405 (0x195) - 3741 (0xe9d) 404 (0x194) - 3732 (0xe94) 403 (0x193) - 3723 (0xe8b) 402 (0x192) - 3714 (0xe82) 401 (0x191) - 3705 (0xe79) 400 (0x190) - 3696 (0xe70) 399 (0x18f) - 3687 (0xe67) 398 (0x18e) - 3678 (0xe5e) 397 (0x18d) - 3669 (0xe55) 396 (0x18c) - 3660 (0xe4c) 395 (0x18b) - 3651 (0xe43) 394 (0x18a) - 3642 (0xe3a) 393 (0x189) - 3633 (0xe31) 392 (0x188) - 3624 (0xe28) 391 (0x187) - 3615 (0xe1f) 390 (0x186) - 3606 (0xe16) 389 (0x185) - 3597 (0xe0d) 388 (0x184) - 3588 (0xe04) 387 (0x183) - 3579 (0xdfb) 386 (0x182) - 3570 (0xdf2) 385 (0x181) - 3561 (0xde9) 384 (0x180) - 3552 (0xde0) 383 (0x17f) - 3543 (0xdd7) 382 (0x17e) - 3534 (0xdce) 381 (0x17d) - 3525 (0xdc5) 380 (0x17c) - 3516 (0xdbc) 379 (0x17b) - 3507 (0xdb3) 378 (0x17a) - 3498 (0xdaa) 377 (0x179) - 3489 (0xda1) 376 (0x178) - 3480 (0xd98) 375 (0x177) - 3471 (0xd8f) 374 (0x176) - 3462 (0xd86) 373 (0x175) - 3453 (0xd7d) 372 (0x174) - 3444 (0xd74) 371 (0x173) - 3435 (0xd6b) 370 (0x172) - 3426 (0xd62) 369 (0x171) - 3417 (0xd59) 368 (0x170) - 3408 (0xd50) 367 (0x16f) - 3399 (0xd47) 366 (0x16e) - 3390 (0xd3e) 365 (0x16d) - 3381 (0xd35) 364 (0x16c) - 3372 (0xd2c) 363 (0x16b) - 3363 (0xd23) 362 (0x16a) - 3354 (0xd1a) 361 (0x169) - 3345 (0xd11) 360 (0x168) - 3336 (0xd08) 359 (0x167) - 3327 (0xcff) 358 (0x166) - 3318 (0xcf6) 357 (0x165) - 3309 (0xced) 356 (0x164) - 3300 (0xce4) 355 (0x163) - 3291 (0xcdb) 354 (0x162) - 3282 (0xcd2) 353 (0x161) - 3273 (0xcc9) 352 (0x160) - 3264 (0xcc0) 351 (0x15f) - 3255 (0xcb7) 350 (0x15e) - 3246 (0xcae) 349 (0x15d) - 3237 (0xca5) 348 (0x15c) - 3228 (0xc9c) 347 (0x15b) - 3219 (0xc93) 346 (0x15a) - 3210 (0xc8a) 345 (0x159) - 3201 (0xc81) 344 (0x158) - 3192 (0xc78) 343 (0x157) - 3183 (0xc6f) 342 (0x156) - 3174 (0xc66) 341 (0x155) - 3165 (0xc5d) 340 (0x154) - 3156 (0xc54) 339 (0x153) - 3147 (0xc4b) 338 (0x152) - 3138 (0xc42) 337 (0x151) - 3129 (0xc39) 336 (0x150) - 3120 (0xc30) 335 (0x14f) - 3111 (0xc27) 334 (0x14e) - 3102 (0xc1e) 333 (0x14d) - 3093 (0xc15) 332 (0x14c) - 3084 (0xc0c) 331 (0x14b) - 3075 (0xc03) 330 (0x14a) - 3066 (0xbfa) 329 (0x149) - 3057 (0xbf1) 328 (0x148) - 3048 (0xbe8) 327 (0x147) - 3039 (0xbdf) 326 (0x146) - 3030 (0xbd6) 325 (0x145) - 3021 (0xbcd) 324 (0x144) - 3012 (0xbc4) 323 (0x143) - 3003 (0xbbb) 322 (0x142) - 2994 (0xbb2) 321 (0x141) - 2985 (0xba9) 320 (0x140) - 2976 (0xba0) 319 (0x13f) - 2967 (0xb97) 318 (0x13e) - 2958 (0xb8e) 317 (0x13d) - 2949 (0xb85) 316 (0x13c) - 2940 (0xb7c) 315 (0x13b) - 2931 (0xb73) 314 (0x13a) - 2922 (0xb6a) 313 (0x139) - 2913 (0xb61) 312 (0x138) - 2904 (0xb58) 311 (0x137) - 2895 (0xb4f) 310 (0x136) - 2886 (0xb46) 309 (0x135) - 2877 (0xb3d) 308 (0x134) - 2868 (0xb34) 307 (0x133) - 2859 (0xb2b) 306 (0x132) - 2850 (0xb22) 305 (0x131) - 2841 (0xb19) 304 (0x130) - 2832 (0xb10) 303 (0x12f) - 2823 (0xb07) 302 (0x12e) - 2814 (0xafe) 301 (0x12d) - 2805 (0xaf5) 300 (0x12c) - 2796 (0xaec) 299 (0x12b) - 2787 (0xae3) 298 (0x12a) - 2778 (0xada) 297 (0x129) - 2769 (0xad1) 296 (0x128) - 2760 (0xac8) 295 (0x127) - 2751 (0xabf) 294 (0x126) - 2742 (0xab6) 293 (0x125) - 2733 (0xaad) 292 (0x124) - 2724 (0xaa4) 291 (0x123) - 2715 (0xa9b) 290 (0x122) - 2706 (0xa92) 289 (0x121) - 2697 (0xa89) 288 (0x120) - 2688 (0xa80) 287 (0x11f) - 2679 (0xa77) 286 (0x11e) - 2670 (0xa6e) 285 (0x11d) - 2661 (0xa65) 284 (0x11c) - 2652 (0xa5c) 283 (0x11b) - 2643 (0xa53) 282 (0x11a) - 2634 (0xa4a) 281 (0x119) - 2625 (0xa41) 280 (0x118) - 2616 (0xa38) 279 (0x117) - 2607 (0xa2f) 278 (0x116) - 2598 (0xa26) 277 (0x115) - 2589 (0xa1d) 276 (0x114) - 2580 (0xa14) 275 (0x113) - 2571 (0xa0b) 274 (0x112) - 2562 (0xa02) 273 (0x111) - 2553 (0x9f9) 272 (0x110) - 2544 (0x9f0) 271 (0x10f) - 2535 (0x9e7) 270 (0x10e) - 2526 (0x9de) 269 (0x10d) - 2517 (0x9d5) 268 (0x10c) - 2508 (0x9cc) 267 (0x10b) - 2499 (0x9c3) 266 (0x10a) - 2490 (0x9ba) 265 (0x109) - 2481 (0x9b1) 264 (0x108) - 2472 (0x9a8) 263 (0x107) - 2463 (0x99f) 262 (0x106) - 2454 (0x996) 261 (0x105) - 2445 (0x98d) 260 (0x104) - 2436 (0x984) 259 (0x103) - 2427 (0x97b) 258 (0x102) - 2418 (0x972) 257 (0x101) - 2409 (0x969) 256 (0x100) - 2400 (0x960) 255 (0xff) - 2391 (0x957) 254 (0xfe) - 2382 (0x94e) 253 (0xfd) - 2373 (0x945) 252 (0xfc) - 2364 (0x93c) 251 (0xfb) - 2355 (0x933) 250 (0xfa) - 2346 (0x92a) 249 (0xf9) - 2337 (0x921) 248 (0xf8) - 2328 (0x918) 247 (0xf7) - 2319 (0x90f) 246 (0xf6) - 2310 (0x906) 245 (0xf5) - 2301 (0x8fd) 244 (0xf4) - 2292 (0x8f4) 243 (0xf3) - 2283 (0x8eb) 242 (0xf2) - 2274 (0x8e2) 241 (0xf1) - 2265 (0x8d9) 240 (0xf0) - 2256 (0x8d0) 239 (0xef) - 2247 (0x8c7) 238 (0xee) - 2238 (0x8be) 237 (0xed) - 2229 (0x8b5) 236 (0xec) - 2220 (0x8ac) 235 (0xeb) - 2211 (0x8a3) 234 (0xea) - 2202 (0x89a) 233 (0xe9) - 2193 (0x891) 232 (0xe8) - 2184 (0x888) 231 (0xe7) - 2175 (0x87f) 230 (0xe6) - 2166 (0x876) 229 (0xe5) - 2157 (0x86d) 228 (0xe4) - 2148 (0x864) 227 (0xe3) - 2139 (0x85b) 226 (0xe2) - 2130 (0x852) 225 (0xe1) - 2121 (0x849) 224 (0xe0) - 2112 (0x840) 223 (0xdf) - 2103 (0x837) 222 (0xde) - 2094 (0x82e) 221 (0xdd) - 2085 (0x825) 220 (0xdc) - 2076 (0x81c) 219 (0xdb) - 2067 (0x813) 218 (0xda) - 2058 (0x80a) 217 (0xd9) - 2049 (0x801) 216 (0xd8) - 2040 (0x7f8) 215 (0xd7) - 2031 (0x7ef) 214 (0xd6) - 2022 (0x7e6) 213 (0xd5) - 2013 (0x7dd) 212 (0xd4) - 2004 (0x7d4) 211 (0xd3) - 1995 (0x7cb) 210 (0xd2) - 1986 (0x7c2) 209 (0xd1) - 1977 (0x7b9) 208 (0xd0) - 1968 (0x7b0) 207 (0xcf) - 1959 (0x7a7) 206 (0xce) - 1950 (0x79e) 205 (0xcd) - 1941 (0x795) 204 (0xcc) - 1932 (0x78c) 203 (0xcb) - 1923 (0x783) 202 (0xca) - 1914 (0x77a) 201 (0xc9) - 1905 (0x771) 200 (0xc8) - 1896 (0x768) 199 (0xc7) - 1887 (0x75f) 198 (0xc6) - 1878 (0x756) 197 (0xc5) - 1869 (0x74d) 196 (0xc4) - 1860 (0x744) 195 (0xc3) - 1851 (0x73b) 194 (0xc2) - 1842 (0x732) 193 (0xc1) - 1833 (0x729) 192 (0xc0) - 1824 (0x720) 191 (0xbf) - 1815 (0x717) 190 (0xbe) - 1806 (0x70e) 189 (0xbd) - 1797 (0x705) 188 (0xbc) - 1788 (0x6fc) 187 (0xbb) - 1779 (0x6f3) 186 (0xba) - 1770 (0x6ea) 185 (0xb9) - 1761 (0x6e1) 184 (0xb8) - 1752 (0x6d8) 183 (0xb7) - 1743 (0x6cf) 182 (0xb6) - 1734 (0x6c6) 181 (0xb5) - 1725 (0x6bd) 180 (0xb4) - 1716 (0x6b4) 179 (0xb3) - 1707 (0x6ab) 178 (0xb2) - 1698 (0x6a2) 177 (0xb1) - 1689 (0x699) 176 (0xb0) - 1680 (0x690) 175 (0xaf) - 1671 (0x687) 174 (0xae) - 1662 (0x67e) 173 (0xad) - 1653 (0x675) 172 (0xac) - 1644 (0x66c) 171 (0xab) - 1635 (0x663) 170 (0xaa) - 1626 (0x65a) 169 (0xa9) - 1617 (0x651) 168 (0xa8) - 1608 (0x648) 167 (0xa7) - 1599 (0x63f) 166 (0xa6) - 1590 (0x636) 165 (0xa5) - 1581 (0x62d) 164 (0xa4) - 1572 (0x624) 163 (0xa3) - 1563 (0x61b) 162 (0xa2) - 1554 (0x612) 161 (0xa1) - 1545 (0x609) 160 (0xa0) - 1536 (0x600) 159 (0x9f) - 1527 (0x5f7) 158 (0x9e) - 1518 (0x5ee) 157 (0x9d) - 1509 (0x5e5) 156 (0x9c) - 1500 (0x5dc) 155 (0x9b) - 1491 (0x5d3) 154 (0x9a) - 1482 (0x5ca) 153 (0x99) - 1473 (0x5c1) 152 (0x98) - 1464 (0x5b8) 151 (0x97) - 1455 (0x5af) 150 (0x96) - 1446 (0x5a6) 149 (0x95) - 1437 (0x59d) 148 (0x94) - 1428 (0x594) 147 (0x93) - 1419 (0x58b) 146 (0x92) - 1410 (0x582) 145 (0x91) - 1401 (0x579) 144 (0x90) - 1392 (0x570) 143 (0x8f) - 1383 (0x567) 142 (0x8e) - 1374 (0x55e) 141 (0x8d) - 1365 (0x555) 140 (0x8c) - 1356 (0x54c) 139 (0x8b) - 1347 (0x543) 138 (0x8a) - 1338 (0x53a) 137 (0x89) - 1329 (0x531) 136 (0x88) - 1320 (0x528) 135 (0x87) - 1311 (0x51f) 134 (0x86) - 1302 (0x516) 133 (0x85) - 1293 (0x50d) 132 (0x84) - 1284 (0x504) 131 (0x83) - 1275 (0x4fb) 130 (0x82) - 1266 (0x4f2) 129 (0x81) - 1257 (0x4e9) 128 (0x80) - 1248 (0x4e0) 127 (0x7f) - 1239 (0x4d7) 126 (0x7e) - 1230 (0x4ce) 125 (0x7d) - 1221 (0x4c5) 124 (0x7c) - 1212 (0x4bc) 123 (0x7b) - 1203 (0x4b3) 122 (0x7a) - 1194 (0x4aa) 121 (0x79) - 1185 (0x4a1) 120 (0x78) - 1176 (0x498) 119 (0x77) - 1167 (0x48f) 118 (0x76) - 1158 (0x486) 117 (0x75) - 1149 (0x47d) 116 (0x74) - 1140 (0x474) 115 (0x73) - 1131 (0x46b) 114 (0x72) - 1122 (0x462) 113 (0x71) - 1113 (0x459) 112 (0x70) - 1104 (0x450) 111 (0x6f) - 1095 (0x447) 110 (0x6e) - 1086 (0x43e) 109 (0x6d) - 1077 (0x435) 108 (0x6c) - 1068 (0x42c) 107 (0x6b) - 1059 (0x423) 106 (0x6a) - 1050 (0x41a) 105 (0x69) - 1041 (0x411) 104 (0x68) - 1032 (0x408) 103 (0x67) - 1023 (0x3ff) 102 (0x66) - 1014 (0x3f6) 101 (0x65) - 1005 (0x3ed) 100 (0x64) - 996 (0x3e4) 99 (0x63) - 987 (0x3db) 98 (0x62) - 978 (0x3d2) 97 (0x61) - 969 (0x3c9) 96 (0x60) - 960 (0x3c0) 95 (0x5f) - 951 (0x3b7) 94 (0x5e) - 942 (0x3ae) 93 (0x5d) - 933 (0x3a5) 92 (0x5c) - 924 (0x39c) 91 (0x5b) - 915 (0x393) 90 (0x5a) - 906 (0x38a) 89 (0x59) - 897 (0x381) 88 (0x58) - 888 (0x378) 87 (0x57) - 879 (0x36f) 86 (0x56) - 870 (0x366) 85 (0x55) - 861 (0x35d) 84 (0x54) - 852 (0x354) 83 (0x53) - 843 (0x34b) 82 (0x52) - 834 (0x342) 81 (0x51) - 825 (0x339) 80 (0x50) - 816 (0x330) 79 (0x4f) - 807 (0x327) 78 (0x4e) - 798 (0x31e) 77 (0x4d) - 789 (0x315) 76 (0x4c) - 780 (0x30c) 75 (0x4b) - 771 (0x303) 74 (0x4a) - 762 (0x2fa) 73 (0x49) - 753 (0x2f1) 72 (0x48) - 744 (0x2e8) 71 (0x47) - 735 (0x2df) 70 (0x46) - 726 (0x2d6) 69 (0x45) - 717 (0x2cd) 68 (0x44) - 708 (0x2c4) 67 (0x43) - 699 (0x2bb) 66 (0x42) - 690 (0x2b2) 65 (0x41) - 681 (0x2a9) 64 (0x40) - 672 (0x2a0) 63 (0x3f) - 663 (0x297) 62 (0x3e) - 654 (0x28e) 61 (0x3d) - 645 (0x285) 60 (0x3c) - 636 (0x27c) 59 (0x3b) - 627 (0x273) 58 (0x3a) - 618 (0x26a) 57 (0x39) - 609 (0x261) 56 (0x38) - 600 (0x258) 55 (0x37) - 591 (0x24f) 54 (0x36) - 582 (0x246) 53 (0x35) - 573 (0x23d) 52 (0x34) - 564 (0x234) 51 (0x33) - 555 (0x22b) 50 (0x32) - 546 (0x222) 49 (0x31) - 537 (0x219) 48 (0x30) - 528 (0x210) 47 (0x2f) - 519 (0x207) 46 (0x2e) - 510 (0x1fe) 45 (0x2d) - 501 (0x1f5) 44 (0x2c) - 492 (0x1ec) 43 (0x2b) - 483 (0x1e3) 42 (0x2a) - 474 (0x1da) 41 (0x29) - 465 (0x1d1) 40 (0x28) - 456 (0x1c8) 39 (0x27) - 447 (0x1bf) 38 (0x26) - 438 (0x1b6) 37 (0x25) - 429 (0x1ad) 36 (0x24) - 420 (0x1a4) 35 (0x23) - 411 (0x19b) 34 (0x22) - 402 (0x192) 33 (0x21) - 393 (0x189) 32 (0x20) - 384 (0x180) 31 (0x1f) - 375 (0x177) 30 (0x1e) - 366 (0x16e) 29 (0x1d) - 357 (0x165) 28 (0x1c) - 348 (0x15c) 27 (0x1b) - 339 (0x153) 26 (0x1a) - 330 (0x14a) 25 (0x19) - 321 (0x141) 24 (0x18) - 312 (0x138) 23 (0x17) - 303 (0x12f) 22 (0x16) - 294 (0x126) 21 (0x15) - 285 (0x11d) 20 (0x14) - 276 (0x114) 19 (0x13) - 267 (0x10b) 18 (0x12) - 258 (0x102) 17 (0x11) - 249 (0xf9) 16 (0x10) - 240 (0xf0) 15 (0xf) - 231 (0xe7) 14 (0xe) - 222 (0xde) 13 (0xd) - 213 (0xd5) 12 (0xc) - 204 (0xcc) 11 (0xb) - 195 (0xc3) 10 (0xa) - 186 (0xba) 9 (0x9) - 177 (0xb1) 8 (0x8) - 168 (0xa8) 7 (0x7) - 159 (0x9f) 6 (0x6) - 150 (0x96) 5 (0x5) - 141 (0x8d) 4 (0x4) - 132 (0x84) 3 (0x3) - 123 (0x7b) 2 (0x2) - 114 (0x72) 1 (0x1) - 105 (0x69) 0 (0x0) - 96 (0x60)
f
f
f
f
minlen只是所有定长列的最小长度
minlen和maxlen
sql2000中的sysindexes表包含了minlen和maxlen列,用于存储一条记录的最小/最大长度
sql2005只能通过indexproperty()函数使用无文档记载的参数来获得
对于只包含定长列的表,indexproperty()函数返回的minlen值等于所有的列长度之和
sys.columns.max_length乘以4字节,这不包括用于存储列数量的2字节以及用于null位图的字节
f
firstpage转换为的值先按照字节交换得到0001000004cf,前面两组表示2字节的文件号,后4个字节表示页面号,因此文件号是0x0001,即1
页面号是0x000004cf,换成十进制即1231
f
写一个专用函数来反转十六进制值,而不是每次都去反转
CREATE FUNCTION convert_page_nums(@page_num binary(6)) RETURNS VARCHAR(11) AS BEGIN RETURN( CONVERT(VARCHAR(2),( CONVERT(INT,SUBSTRING(@page_num,6,1))* POWER(2,8) ) + (CONVERT(INT,SUBSTRING(@page_num,5,1))) ) + ':' + CONVERT(VARCHAR(11), (CONVERT(INT,SUBSTRING(@page_num,4,1)) * POWER(2,24)) + (CONVERT(INT,SUBSTRING(@page_num,3,1)) * POWER(2,16)) + (CONVERT(INT,SUBSTRING(@page_num,2,1)) * POWER(2,8)) + (CONVERT(INT,SUBSTRING(@page_num,1,1))) ) ) END SELECT dbo.convert_page_nums(0x6E0000000100);
SQL Server:将6字节的十六进制页面号转化成【文件号:页面号】格式函数
http://www.cnblogs.com/xbf321/archive/2009/09/12/1565291.html
f
f
找到列偏移
syscolumn不再可靠
SELECT c.[name] AS columnname , c.[column_id] , pc.[max_inrow_length] , [pc].[system_type_id] , [pc].[leaf_offset] FROM sys.[system_internals_partition_columns] pc JOIN sys.[partitions] p ON p.[partition_id] = pc.[partition_id] JOIN sys.[columns] c ON [column_id] = [partition_column_id] AND c.[object_id] = p.[object_id] WHERE p.[object_id] = OBJECT_ID('aa')
堆表也是一样的
f
位类型bit
m_slotCnt = 700
为什麽只能容纳700行数据
2状态A+状态B+2定长数据的大小+1定长数据内容+2列数量+1null位图=8字节
8字节*700行=5.6kb 数据内容
700行*2字节=1.4kb 行偏移矩阵
5.6+1.4=7kb 差不多一个数据页
f
f
f
f
f
USE [sss] --DROP TABLE hugerows CREATE TABLE hugerows ( a VARCHAR(3000) , b VARCHAR(8000) , c VARCHAR(8000) , d VARCHAR(8000) ) INSERT INTO hugerows SELECT REPLICATE('a',3000),REPLICATE('b',3000),REPLICATE('c',4000),REPLICATE('d',3000) TRUNCATE TABLE [DBCCResult] INSERT INTO DBCCResult EXEC ('DBCC IND(sss,hugerows,-1) ') SELECT * FROM DBCCResult DBCC TRACEON(3604,-1) GO DBCC PAGE([sss],1,260,3) GO
行溢出页面也有IAM页面进行跟踪
f
f
f
f
对大表关闭text in row选项会马上对lob数据移动回去原始数据页面
一个根结构最少有24字节长,这就是为什么24是text in row限制的最小尺寸
根中的其他信息
0~1字节:列类型,1表是lob根
第2字节:b树中的层次
第3字节:未使用
4~7字节:每次更新lob都会增长的一个值,用于优化游标的并发控制
8~11字节:DBCC CHECKTABLE使用的一个随机值,在每个lob数据的生命周期中保持不变
12~23字节:列中随后的12字节组,链接到一个独立页面上的lob数据块
f
lob数据类型可以使用update,select ,insert也可以使用readtext,writetext,updatetext,他们需要处理字节偏移
max分类符,定义变长列 ,例如varchar(max)
f
半结构化的数据类型sysvariant
sysvariant数据类型功能是为支持sqlserver上层产品的半结构化数据而设计的
微软的 outlook和exchange中的email信息就是一个例子,通过SQL_VARIANT数据类型,我们可以将一个表概念表转化为一个真实的,拥有一些属性值对的,更加紧凑的表
f
USE [sss] --DROP TABLE variant CREATE TABLE variant(a INT ,b SQL_VARIANT) INSERT INTO variant SELECT 1,'1' UNION ALL SELECT 3,'abc' UNION ALL SELECT 4,'2013-8-1' TRUNCATE TABLE [DBCCResult] INSERT INTO DBCCResult EXEC ('DBCC IND(sss,variant,-1) ') SELECT * FROM [DBCCResult] SELECT * FROM variant DBCC TRACEON(3604,-1) GO DBCC PAGE([sss],1,266,3) GO DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 PAGE: (1:266) BUFFER: BUF @0x0000000088FEBF00 bpage = 0x0000000088CA8000 bhash = 0x0000000000000000 bpageno = (1:266) bdbid = 8 breferences = 0 bcputicks = 0 bsampleCount = 0 bUse1 = 29940 bstat = 0xc0000b blog = 0x21bbbbbb bnext = 0x0000000000000000 PAGE HEADER: Page @0x0000000088CA8000 m_pageId = (1:266) m_headerVersion = 1 m_type = 1 m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0x8000 m_objId (AllocUnitId.idObj) = 218 m_indexId (AllocUnitId.idInd) = 256 Metadata: AllocUnitId = 72057594052214784 Metadata: PartitionId = 72057594048741376 Metadata: IndexId = 0 Metadata: ObjectId = 581837385 m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 8 m_slotCnt = 3 m_freeCnt = 8009 m_freeData = 177 m_reservedCnt = 0 m_lsn = (221:408:32) m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 0 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED Slot 0 Offset 0x60 Length 24 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 24 Memory Dump @0x000000000DAAC060 0000000000000000: 30000800 01000000 02000001 001800a7 †0............... 0000000000000010: 01080024 d0000031 †††††††††††††††††††...$...1 Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4 a = 1 Slot 0 Column 2 Offset 0xf Length 9 Length (physical) 9 b = 1 Slot 1 Offset 0x78 Length 26 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 26 Memory Dump @0x000000000DAAC078 0000000000000000: 30000800 03000000 02000001 001a00a7 †0............... 0000000000000010: 01080024 d0000061 6263†††††††††††††††...$...abc Slot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4 a = 3 Slot 1 Column 2 Offset 0xf Length 11 Length (physical) 11 b = abc Slot 2 Offset 0x92 Length 31 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 31 Memory Dump @0x000000000DAAC092 0000000000000000: 30000800 04000000 02000001 001f00a7 †0............... 0000000000000010: 01080024 d0000032 3031332d 382d31††††...$...2013-8-1 Slot 2 Column 1 Offset 0x4 Length 4 Length (physical) 4 a = 4 Slot 2 Column 2 Offset 0xf Length 16 Length (physical) 16 b = 2013-8-1 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
f
列类型
系统表sys.[types]
系统表sys.[columns]
SELECT [scol].[name] , [stype].[name] FROM sys.[types] AS stype JOIN sys.[columns] AS scol ON [scol].[system_type_id] = [stype].[system_type_id] AND [scol].[user_type_id] = [stype].[user_type_id]
f
f
f
约束名是架构范围的,这意味着他们共享同一个命名空间,因此在一个架构内必须唯一,在同一架构内,不能有两个相同的primary key 约束的表
USE [xxx_MinimalLogged] SELECT * FROM sys.[objects] WHERE [object_id]=(SELECT [parent_object_id],[object_id] FROM sys.[objects] WHERE [object_id]=0x67c95aea)
f
f
f
修改表列注意事项
不能修改text,image,ntext,rowversion列的数据类型
如果修改列是rowguidcol,则只允许drop rowguidcol,而不允许改变数据类型
被修改列不能是一个计算列或被复制的列
被修改列是不能定义有primary key或foreign key约束
被修改列不能被计算列引用
如果有check约束和unique约束,只能修改列长度
旧数据类型必须运行隐式转换为新数据类型
如果适用,新类型默认开启ansi_padding选项,不论当前设置如何
如果将一个旧的类型转换为新的类型会引起溢出的话,alter table会终止
f
f
SELECT [is_not_trusted] FROM sys.[check_constraints] SELECT [is_not_trusted] FROM sys.[foreign_keys]
[is_not_trusted]如果使用了WITH NOCHECK [is_not_trusted]就会是1
删除一个列的限制
一个被复制的列
被某个索引使用的列
被check ,foreign key,unique,primary key约束使用的列
通过default关键字与某个默认值有关或者被绑定到某个默认对象的列
与某个规则rule绑定的列
f
对表进行增删列一般只会改变元数据,并且会记录到日志
f
f
f
删除旧列可能只影响update语句,因为insert的时候是全新的记录,update旧值,delete
f
第七章 索引的内部构造和管理
f
f
f
f
f
f
leading column mysql中的前导列
f
f
f
f
IAM链 (一个连接一张表或索引的一个分区上的相同类型的页面链 例如 lob,row-over-flow,inrow-data)
对于堆表,root_page存储了最后一个页面的指针,对于堆表,最前和最后没有意义
DBCC IND命令详细解释,还可以指定分区号
f
3=lob_mixed_page
4=lob_tree_page
f
f
USE [sss] GO CREATE TABLE clustered_dupes ( col1 CHAR(5) NOT NULL , col2 INT NOT NULL , col3 CHAR(3) NULL , col4 CHAR(6) NOT NULL ) GO CREATE CLUSTERED INDEX C1_DUPES_COL1 ON clustered_dupes(col1) SELECT [first] , [indid] , [keycnt] , [name] FROM sys.[sysindexes] WHERE id = OBJECT_ID('clustered_dupes') first indid keycnt name -------------- ------ ------ -------------------------------------------------------------------------------------------------------------------------------- 0x000000000000 1 2 C1_DUPES_COL1 sqlserver在需要的时候才添加唯一标识符, 字段keycnt(代表一个索引具有的键的数量)的值就是2(注意该字段只在兼容视图sysindexes中可用,而目录视图sys.indexes中则不可用)如果在创建该索引时使用了unique限定词,keycnt的值就是1,如果在堆表中查看sysindexes中keycnt的值就是0
f
每两个十六进制字符代表一个字节
对于字符字段,可以将每个字节看作是一个ASCII码并将其转换成相关字符
数字是先存储低位,因此每个数字字段内,必须将两个字节交换后计算到底存了什么数值
f
null也是变长列
f
f
f
f
f
非聚集索引中的rid的顺序:页面号:文件号:slot号
f
f
keyhashvalue是通过哈希公式派生出来的定长字符串,该数值在某些其他工具中用来代表行记录
f
f
f
f
f
f
f
SELECT * FROM sys.[dm_db_partition_stats]
每个分区中的每种类型页面的页面数量和行数
每行返回一个分区所有信息
包含三种页面类型的使用信息inrow-data,overflow-data,lob-data
f
USE [sss] SELECT * FROM sys.[dm_db_partition_stats] WHERE [object_id] = OBJECT_ID('aaa')
f
f
f
使用EXEC SP_SPACEUSED来查看表以及索引的总空间
但是给出的结果不是最新的,特别进行了大容量操作,这时候可以使用@updateusage参数或者执行DBCC UPDATEUSAGE来强制这些sqlserver的早期版本更新内部元数据
f
sql2005允许在计算列上建索引和在视图上建索引,这些都会进行物理存储
f
set选项
测试选项是否合理
SELECT SESSIONPROPERTY('ANSI_NULLS')
f
f
确定性函数:每次输入相同的值返回的结果都相同
非确定性函数:每次输入相同的值返回的结果都不同
判断一个函数是确定性还是非确定性
SELECT OBJECTPROPERTY(OBJECT_ID('Avg'),'IsDeterministic')
f
建索引视图架构绑定的意思
WITH SCHEMABINDING,建索引视图本身要求基准对象的架构不能改变,为了防止改变,必须在建视图时指定WITH SCHEMABINDING,建索引视图后,如果所引用表发生架构变化就会报错
CREATE VIEW aa WITH SCHEMABINDING
f
不能在非确定性的计算列上创建索引
f
使用COLUMNPROPERTY()确定列的确定性
SELECT COLUMNPROPERTY(OBJECT_ID('aaa'),'name','IsDeterministic')
f
persisted columns持久化列
f
f
删除计算列只涉及元数据的操作,然后将其重新定义为持久化字段
COLUMNPROPERTY函数判断持久化字段是否是精确的
定义分区字段时也可以使用持久化字段
f
物化视图,索引视图申请的锁会很多 高继伟
索引视图就是ORACLE的物化视图
在索引视图上建立的索引必须是唯一聚集索引,以便物化
f
索引视图不能使用order by定义
f
所有group by字段也必须出现在select列表中
可以使用OBJECTPROPERTY的IsIndexable属性来判断基表是否适合创建索引视图
USE [sss]
SELECT OBJECTPROPERTY(OBJECT_ID('aaa'),'IsIndexable')
创建索引视图
f
f
可以使用OBJECTPROPERTY来检查索引视图已经索引化,物理化
一旦索引化就可以在元数据,目录视图里获取位置和空间大小信息
USE [sss] SELECT OBJECTPROPERTY(OBJECT_ID('aaa'),'IsIndexable')
sqlserver企业版
f
使用(NOEXPAND)查询提示sqlserver使用索引视图而不查询基准表
SELECT * FROM [dbo].[aaa] WITH (NOEXPAND)
f
表和索引分区
没有指向任何分区而创建的表和索引被认为是存储在单个分区上的
获取数据存储相关信息最有用的元数据对象之一是DMV[dm_db_partition_stats]
他集合了sys.[partitions], sys.[indexes],sys.[allocation_units]中的相关信息
SELECT * FROM sys.[dm_db_partition_stats] WHERE [object_id]=OBJECT_ID('aaa')
在sql2000中只能手动创建视图来联合多个表的方法才能实现分区,这项功能被称为partitioned views,分区视图
sql2005只有分布式分区视图,而没有sql2000的分区视图,两者本质上一样也有不一样
f
分区函数,分区方案
分区元数据
f
分区函数,12个分区,11个端点
f
关于分区的元数据
分区相关的视图
f
f
f
使用DAC连接也删除不了这些表,但是这些系统表可以用sqlprompt看到表定义
DROP TABLE syssingleobjrefs 消息 3701,级别 11,状态 5,第 1 行 无法对 表 'syssingleobjrefs' 执行 删除,因为它不存在,或者您没有所需的权限。
CREATE TABLE [sys].[syssingleobjrefs]
(
[class] [tinyint] NOT NULL,
[depid] [int] NOT NULL,
[depsubid] [int] NOT NULL,
[indepid] [int] NOT NULL,
[indepsubid] [int] NOT NULL,
[status] [int] NOT NULL
) ON [PRIMARY]
GO
f
数据的移动实际上在元数据里修改表sys.partitions和sys.[system_internals_allocation_units]
可以将表分区一的数据移动到分区二里面
ALTER TABLE xx SWITCH PARTITION 1 TO xx PARTITION 2 GO
f
f
构建在与基本表相同的分区方案上的索引被称为对齐索引(aligned indexes)
索引对齐
如果分区依据列(简称分区列)不是索引定义的一部分,sqlserver会将分区列作为一个额外的包含列(including column)加到该索引中,如果该索引是聚集索引,添加一个包含列是没有必要的,因为聚集索引总是包括所有的列。另一个关于sqlserver不自动添加包含列的问题是当你创建一个(聚集或非聚集的)唯一索引的时候,由于唯一分区索引的一个必要条件是分区列必须被包括在唯一键值(unique key)中,一个没有显式包含分区键值的唯一索引不会被自动分区,不能交换分区
如果是索引对齐的,那么每个索引都会包含分区依据列,这里的分区依据列是classid
USE [xxx] CREATE TABLE DBCCResult ( PageFID NVARCHAR(200) , PagePID NVARCHAR(200) , IAMFID NVARCHAR(200) , IAMPID NVARCHAR(200) , ObjectID NVARCHAR(200) , IndexID NVARCHAR(200) , PartitionNumber NVARCHAR(200) , PartitionID NVARCHAR(200) , iam_chain_type NVARCHAR(200) , PageType NVARCHAR(200) , IndexLevel NVARCHAR(200) , NextPageFID NVARCHAR(200) , NextPagePID NVARCHAR(200) , PrevPageFID NVARCHAR(200) , PrevPagePID NVARCHAR(200) ) TRUNCATE TABLE DBCCResult INSERT INTO DBCCResult EXEC ('DBCC IND([xxx],xxxsifyResult,-1) ') SELECT TOP 10 * FROM DBCCResult WHERE pagetype=2 AND indexid=10 SELECT DISTINCT(indexid) FROM DBCCResult WHERE pagetype=2 DBCC TRACEON(3604,-1) GO DBCC PAGE([xxxxx095],3,33921,3) GO
f
f
f
索引管理器
f
f
f
f
f
被删除的页面不会标记为未分配状态,因此这部分空间无法供其他对象使用
f
鬼影记录 ghost record
f
f
更新究竟是查询处理器还是存储引擎控制
f
因此,当且仅当聚集索引键被更新时,才需要在每个非聚集索引中进行相应的修改,请在决定要在哪些字段上建立聚集索引的时候牢记这点
最好在非易失性(nonvolatile)的字段上创建聚集索引
forwarding pointer前转指针
f
有前转指针的记录
Slot 2 Offset 0x1feb Length 9
Record Type = FORWARDING_STUB Record Attributes = Record Size = 9
Memory Dump @0x000000000FCBBFEB
0000000000000000: 040e0100 00010000 00†††††††††††††††††.........
Forwarding to = file 1 page 270 slot 0
将04十六进制反转40 再转为二进制 01000000
bit1-3: 0=(primary record);1=(forwarded record);2=(forwarding stud);3=(index record);4=(溢出数据);5=(ghost索引记录);6=(ghost数据记录)
十进制6,二进制110
-------------------------------------------------------------
一般的记录
Slot 4 Offset 0x199c Length 1615
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 1615
Memory Dump @0x000000000FCBB99C
0000000000000000: 30000800 05000000 03000001 004f0665 †0............O.e
将30十六进制反转03 再转为二进制 00000011
bit1-3: 0=(primary record);1=(forwarded record);2=(forwarding stud);3=(index record);4=(溢出数据);5=(ghost索引记录);6=(ghost数据记录)
------------------------------------------------------------------------------------------------
已转向记录
Slot 0 Offset 0x6bb Length 3229
Record Type = FORWARDED_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 3229
Memory Dump @0x000000000F2DA6BB
0000000000000000: 32000800 03000000 03000003 00530693 †2......
如果一条前转指针forwarding pointer已经被前转的记录再次移动时,最初的前转指针就被更新并指向新的位置,如果还要继续移动,那么前转指针就会不断地指向另一个前转指针。
另外,如果前转记录收缩到其原始位置足以能够容纳时,这条记录就会被移回到原始位置back-pointer(再次update的时候,当新值跟原来的旧值尺寸一样,会移动回去),如果数据页还有可用空间的话,前转指针就会被删除
f
forwarding pointer的文章
paul大牛
http://www.sqlskills.com/blogs/paul/forwarding-and-forwarded-records-and-the-back-pointer-size/
sqlserver magazine
http://sqlmag.com/stored-procedures/removing-forwarded-records-heap-tables
Dmitri Korotkevitch大牛的文章forwarding pointer指针长度16字节 ,实际上是9个字节
http://www.cnblogs.com/lyhabc/articles/3815148.html
力伟的文章写到
而这个pointer大小为9 byte(header占一byte,RID占8byte,RID的构成:4个字节的pageID,2个字节的fileID,2个字节的slotID)。
所以sql server为了保证能够成功地将数据行替换成forwarding pointer,规定每个数据行要最少要占用9个byte。
back pointer的解释
Anatomy of a Forwarded Record & the Back Pointer
http://improve.dk/anatomy-of-a-forwarded-record-ndash-the-back-pointer/
0000000000000000: 040e0100 00010000 00†††††††††††††††††.........
Forwarding to = file 1 page 270 slot 0
第一个字节04 状态A
接下来的四个字节 翻译为页面号 0e0100 00 翻转为0000010e 十进制为270
0100 翻转为 0001
00 00 翻转为 0000
1:270:0
前转指针的清除有两种情况:
1、更新新值的时候与原值尺寸一样
2、当收缩数据库时会为书签进行再分配,前转指针会被删除
使用sys.[dm_db_index_physical_stats]查看各个表的前转指针的数量
SELECT forwarded_record_count , DB_NAME(database_id) AS db , OBJECT_NAME(object_id) AS tablename , * FROM sys.[dm_db_index_physical_stats](DB_ID(), NULL, NULL, NULL, NULL)
原位更新
非原位更新
f
f
sqlserver实际使用的是其内部的行标识符,这里将标识符简化为rowid,update操作会生成输入流input stream
f
使用拆分和合并的更新操作
split-》collapse
--update操作的执行计划 USE [sss] CREATE TABLE testupdate(x INT PRIMARY KEY,y INT) INSERT testupdate VALUES(1,10) INSERT testupdate VALUES(2,10) UPDATE [dbo].[testupdate] SET x=3-x
f
表级修改row-at-a-time
索引级修改 index-at-a-time
两种修改策略的日志量都是相等的
f
f
sqlserver早期版本,例如sql6.5建议使用大容量插入的时候最好先删除所有非聚集索引,因为这样就不会提供索引级策略来维护全部索引了,不用提供表假脱机了
在语句提交或在事务被调用的应用程序承认之前,这些修改必须落盘记录到事务日志
f
f
SQL2005提供了ALTER INDEX的功能,代替以前的各种索引维护命令
例如:sp_indexoption,update statistics,dbcc dbreindex,dbcc indexdefrag
f
f
不要禁用表上的聚集索引,这样的话所有的数据都不可用!!
碎片会在堆以及索引中发生,但是这类讨论多是集中在索引的碎片上的
碎片有两种:内部碎片和外部碎片
f
碎片种类
f
sys.[dm_db_index_physical_stats](DB_ID(), NULL, NULL, NULL, NULL)取代了DBCC SHOWCONTIG
f
f
f
三种扫描模式
LIMITED:最快速度扫描页面,只扫描索引的父级页面,不会扫描索引的叶子页面
SAMPLED:百分之一采样频率返回统计信息
DETAILED:扫描所有页面
注意输入参数如果db_id()返回的是null的值,那么sys.[dm_db_index_physical_stats]不会有任何提示,他会按照null去处理
F
F
F
f
碎片报告
f
f
内部碎片的百分比
外部碎片的百分比
乱序碎片应该是倒序碎片吧??因为只有索引是物理排序的,所以只有索引才有乱序碎片的说法
f
f
sample模式:每100个页面进行采样,100个页面中第一页
如果表很少,少于10000个页面的话,那么sqlserver会自动将sampled模式转换为detailed模式并检查全部页面
f
f
碎片的移除
version_ghost_record_count:统计了鬼影的一个子集,该数值反馈由一个未完成的快照隔离事务所持有的鬼影记录数量。这些鬼影记录在所有相关事务被提交或者回滚以前都不会清除掉
f
SELECT avg_fragmentation_in_percent FROM sys.[dm_db_index_physical_stats](DB_ID(), NULL, NULL, NULL, NULL)
avg_fragmentation_in_percent值在5~20 进行索引重组
avg_fragmentation_in_percent值>30 重建索引
进行索引碎片整理时会在表上获取意向共享锁
对指定分区进行索引重组
USE [test] ALTER INDEX [PK__testinde__3213E83F92F3B59B] ON [dbo].[testindentity] REORGANIZE PARTITION=2
f
WITH LOB_COMPACTION =ON 允许用户控制LOB数据是否受到磁盘重整的影响,默认值为ON
索引碎片整理的两个阶段:1、压缩 2、重排
f
SQLSERVER使用冒泡排序来做索引重组操作
混合区上的页面是无法进行碎片重组的!!
f
F
CREATE TABLE [dbo].[testindentity] ADD PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON) ON PRIMARY
建立索引的时候 ALLOW_ROW_LOCKS = OFF那么是无法使用索引重组的
F
F
重建索引会在索引上占有排他锁,索引在对索引重建时索引是不可用的
如果是聚集索引那么表不能访问,如果非聚集索引,非聚集索引不能使用
ALTER INDEX和CREATE INDEX都有online选项
F
行记录解释
http://improve.dk/anatomy-of-a-forwarded-record-ndash-the-back-pointer/
http://www.cnblogs.com/trams/archive/2010/09/11/1823727.html
其中状态A为如下说明:
bit0:版本信息,在SQL Server 2005/08总是为0
bit1-3: 0=(primary record);1=(forwarded record);2=(forwarding stud);3=(index record);4=(溢出数据);5=(ghost索引记录);6=(ghost数据记录)
bit4:表示存在NULL位图(在数据行里SQL2005/08总存在NULL位图)
bit5:表示存在变长列
bit6:未启用
bit7:表示存在幽灵记录
本例中30->00110000 它是一个行属性的位图 从高位存到地位(右边第一位是bit0),bit4为1即存在变长列的字段,因为在SQLServer2005/2008中总存在NULL位图,所以bit5也为1。
状态位B在SQLServer2005//2008中未启用,所以为00
记录定长部分的长度为2个字节,是所有定长字段的长度之和加4,该处为int类型4个字节,char(100)为100个字节,再加上4,所以为108,换算成16进制即6c。
紧跟其后的为定长字段的内容,即ID字段的4个字节和TYPE字段的100个字节。
固定长度的字段数据之后,是该表的总字段数,用两个字节表示,本表包括5个字段所以为05 00。
NULL位图:f0->11110000 因为该表只有列 所以只需要看后面个,1表示该行的对应列为NULL或者该位图未使用。本表前4个字段不为空,第5个为空,第6-8未使用。
接下来是行内存储数据的变长列的数目:0200->00000000 00000010=2 表示该行存储了列name和other字段的数据。
第一变长列数据终止位置为:7a00->00000000 01111010=122=1+1+2+(4+100)+2+ceiling(5/8)+2+2+2+len(“name1”)
第二变长列数据终止位置:7b00->00000000 01111011=123 实际上就是在前者的基础上加了第二个变长列的字段长度。
1+1+2+(4+100)+2+ceiling(5/8)+2+2+2+len(“name1”)+len(“8”)
第一列变长列的数据: 6e616d 6531换算成字符即'name1'
第二列变长列的数据:38换算成字符即8
CREATE TABLE ForwardedRecordTest
(
ID int identity,
Data varchar(8000)
)
Record Type = FORWARDED_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 5027
Memory Dump @0x000000000D75C84B
|符号进行字节切割
0000000000000000: 3200|0800| |02000000| 0200|00|02 00|9913a3 †2...............
0000000000000010: 93|626262 62626262 62626262 62626262
0000000000001390: 62626262 62626262 6200040f 01000001 †bbbbbbbbb.......
00000000000013A0: 000100†††††††††††††††††††††††††††††††...
32 不用翻转字节 二进制是00110010 (从高位存到地位(右边第一位是bit0))
00为状态B 不用管
00110010
1=(forwarded record)
bit5:表示存在变长列
0800 反转字节 0008 :记录定长部分的长度为2个字节,是所有定长字段的长度之和加4,该处为int类型4个字节,所以这里是8个字节
UPDATE
ForwardedRecordTest
SET
Data = REPLICATE('b', 5000)
WHERE
Data = REPLICATE('b', 2000)
02000000 定长数据 4个字节 值为2 只是记录定长部分是所有定长字段的长度之和加4,但是实际存储还是使用4个字节
0200 字段数量 2个字节 2个字段
00 null位图 1个字节
02 00 变长列的数量 只有一个变长列,为什么会是2? 其实另一个变长列指的是back pointer field
9913a393 列偏移矩阵 2*varcount字节 2*2=4字节 为什么公式是2*varcount,因为每一个列的列偏移是2个字节,那么将9913|a393切开
1399转为十进制 5017 ,93a3 转为十进制 37795 37795超出了页面的阀值 转为二进制 1001001110100011 将高位去掉0001001110100011 转为十进制5027
减去1399 的十进制即 5027-5017=10 即 可以得出back pointer占10个字节
626262 为实际数据
Data varchar(8000)
REPLICATE('b', 5000)
虽然是varchar数据类型,但是一个字符只占一个字节,那么就是在5000个62之后的位置就是back pointer
0000000000001390: 62626262 62626262 6200040f 01000001 †bbbbbbbbb.......
00000000000013A0: 000100†††††††††††††††††††††††††††††††...
00040f 01000001 000100 10个字节
0004 前两个字节 指明columnid 因为back pointer作为表中的一个列,400算出columnid的值为1024 我查询sys.[columns]并没有columnid为1024这个列
所有forwarded record 记录的columnid都为0004 即1024 应该是作为一个标记,指明sqlserver这是一个back pointer
0f010000 4个字节 页面号 翻转 0000010f 转为十进制271 原来的页面号就是271
0100 2个字节 文件号 1
0100 2个字节 行号 1
UPDATE
ForwardedRecordTest
SET
Data = REPLICATE('a', 7000)
WHERE
Data = REPLICATE('a', 2000)
0000000000001B60: 61616161 61616161 6100040f 01000001 †aaaaaaaaa.......
0000000000001B70: 000000†††††††††††††††††††††††††††††††...
00040f 01000001 000000 这个back pointer 跟第二条记录的back pointer是一样的
f
f
对比一下mysql的索引重建
(一:Inplace Add Index)
(二:Online Add Index)
http://hedengcheng.com/?p=405
http://hedengcheng.com/?p=421
Copy Table方式
Inplace方式
Online方式
f
联机索引创建实际上并不认为是一种性能提升,因为事实上,索引在离线时创建速度会更快
sqlserver不必同时维护所有这些结构,而且还需要有足够的磁盘空间,联机索引创建是一种可用性特性保证7*24 数据库的可用性
f
f
f
第八章 锁和并发
f
f
f
f
f
tradeoff:权衡 折衷
f
f
脏读
不可重复读 又叫做不一致分析
f
幻影
f
隔离级别
f
f
f
用户可以设置会话session选项lock_timeout来控制sqlserver等待锁被释放的时长
这是个set选项,因此只能在一个单独的会话中支配其行为,无法对整个sqlserver设置一个lock_timeout值
f
f
interim :中间的过渡时间
f
f
锁升级:escalate locks
f
成熟的:full blown
使用存储过程 EXEC sp_lock 和视图SELECT * FROM sys.[dm_tran_locks]是看不见闩锁的
闩和锁的另一个区别是 锁保证数据的逻辑一致性,闩保证物理一致性
f
自旋锁比闩更加轻量,闩比锁更加轻量
锁粒度 granularity
f
f
转换死锁conversion deadlock
f
意向锁
f
大容量更新锁,架构稳定锁,架构修改锁
f
转换锁conversion locks
f
转换锁或者锁升级
f
键范围锁
锁粒度
f
[dm_tran_locks]显示特定资源的一个标识符identifier,[dm_tran_locks]只是一个DMV,实际的信息存储在sqlserver内部的数据结构中,对用户来说是完全不可见的
f
f
f
可串行化隔离级别,在sql7.0的时候保证一定范围的锁定会在页面甚至表上获取锁
而不像mysql,申请gap锁
sql2005使用键范围锁,相当于mysql的gap锁
这两个键范围锁可以防止其他人插入xx到xx之间的数据,键范围锁实际上是放置两个锁,锁定一段范围,就像mysql的gap锁
键范围锁闭sql7.0锁定整个页面和整个表更有效
f
有9种类型的键范围锁
f
查看[dm_tran_locks]视图中的status的锁定请求来观察键范围锁
区也可以加锁,当一个表或者索引需要增长必须分配新的区时,这类锁就会自动发生
区有共享区锁和扩展区锁
f
延迟删除 128个区
对于master和tempdb是无法删除和关闭的,所以数据库级锁对它们来说是多余的
当删除或在重建大表或索引时,实际的页面回收deallocation操作是被推迟到事务提交以后进行的,延迟(deferred)的删除drop操作并不立即释放已分配的区,而且还引入了额外开销,因此延迟删除操作只在使用了超过128个区的表或索引上完成。如果表或索引少于128个区,删除,截断,重建的操作就和sql2005以前一样,不会有延迟操作发生
在延迟操作的首个阶段里,表或索引所使用的现存分配单元会
f
allocation_unit锁
SELECT * FROM sys.[system_internals_allocation_units] WHERE [type_desc]='droped'
[system_internals_allocation_units]视图里找到[type_desc]为dropped的分配单元,并看到多少空间被分配单元占用,导致这部分空间无法被重用又不属于任何对象,就像tempdb里的对象一样
分配单元空间的实际物理删除操作会在事务提交以后发生
应用程序级锁 application lock
应用程序级锁可以选项锁定任何想要锁住的东西,这些锁定资源就是应用程序级锁
f
检查兼容性时,使用的是为SQLSERVER内建锁而设计的相同的兼容性矩阵
f
f
应用程序锁例子
EXEC SYS.[sp_getapplock] @Resource = N'PROCLOCK', -- nvarchar(255) @LockMode = 'EXCLUSIVE', -- varchar(32) @LockOwner = 'SESSION', -- varchar(32) @LockTimeout = 0, -- int @DbPrincipal = 'PROUSERROLE' -- sysname EXEC MYSPECIALPROC <PARAMETER LISK> EXEC SYS.[sp_releaseapplock] @Resource = N'PROCLOCK', -- nvarchar(255) @LockOwner = 'SESSION' -- varchar(32)
[dm_tran_locks]视图只有[resource_description]会显示锁定资源名称
f
f
keyhashvalue的产生:对于 一个建立在堆上的非聚集索引(c1和c2是索引列)哈希值将由c1列,c2列以及rid加起来生成
区锁 区的第一个页面的文件号:页号
键范围锁和键锁具有相同的资源描述,因为键范围被视为一种锁定模式,而不是一种锁定资源
其他可锁定的资源类型包括hobt和allocation_unit和元数据
f
元数据锁metadata资源被划分为多个子类型(比任何其他资源都要多)由sys.[dm_tran_locks]视图的[resource_subtype]字段类描述
SELECT [resource_subtype] FROM sys.[dm_tran_locks]
SELECT [resource_associated_entity_id] FROM sys.[dm_tran_locks]
[resource_associated_entity_id] 显示了数据库中的那个关联实体的ID,他可以是对象id,hobt id或者分配单元id这取决于资源类型
page,key,rid,hobt提供了一个hobt id视图
f
f
f
一共有四种类型的锁所有者
事务型,游标型,事务工作空间型transaction workspace ,会话型
游标锁
f
通常每个会话对应一个工作空间,所有会话的数据库级锁都保留在相同的工作空间对象中
分布式事务和绑定会话bound session的情况下,多个会话会进入相同的工作空间,因而他们会共享数据库级锁
f
sys.[dm_tran_locks]视图取代了以前的sp_lock存储过程
[resource_subtype]不是每种资源都有子类型,但是metadata例外,metadata有超过40种子类型
f
f
f
f
SELECT [request_owner_guid] FROM sys.[dm_tran_locks]
[request_owner_guid] :供分布式事务使用,在该事务中,该值与事务的DTC GUID相对应
f
f
f
f
f
f
f
f
f
f
f
f
锁饥饿lock starvation”现象
sqlserver通过检查已授权进程以及正在等待进程的锁兼容性,可以防止“锁饥饿lock starvation”现象发生(当共享锁的申请持续不断时会导致排他锁的请求永远不能被批准)
锁是内部的一种内存结构,消耗sqlserver使用的一部分内存
64字节或128字节的内存结构被称为锁块 lock block
f
锁拥有者块 代表了锁和实体之间的关系
f
2的31次方 int 4字节 21亿个槽位
2的11次方 2048
每个锁块15字节字段描述被锁资源
锁哈希表的每个条目大小为16字节
f
在numa配置上,这些锁和锁拥有者块被划分到全部的NUMA节点中去,因此当产生一个锁请求时,会使用numa节点本地的锁块
如果没有使用sp_configure配置锁数量
那么在sqlserver启动时候,sql express分配500个锁块,其他版本分配2500个锁块
分配锁拥有者块的数量是锁块的两倍(2*锁块数)
锁管理器,全局内存管理器,缓存管理器
f
SELECT [resource_lock_partition] FROM sys.[dm_tran_locks]
[resource_lock_partition] 字段表示一个锁的锁分区,因此用户会看到同一资源上的多个锁具有不同的[resource_lock_partition] 值,
对于少于16个CPU的系统来说(根本不会使用锁分区),[resource_lock_partition] 的值始终为0
f
基于锁分区技术,sqlserver分散了对跨多个自旋锁的那些锁进行检查的工作量,并且大多数对任意指定自旋锁的访问都是来自相同的CPU(尤其也总是来自相同的节点),这就意味着自旋锁并不会频繁地旋转
f
注意:
根据本文下面锁升级的描述
由 一条 单条的语句 在 一个对象上(索引或堆) 持有的锁数量超过了阀值
然而,一个事务 在同一个对象上又获取了1250个锁时,SQL Server会继续尝试锁升级
锁升级发生在单条语句或单个事务,因为SQL Server默认就是一个语句一个隐式事务,那么可以概括为:在同一个事务内的锁数量超过阀值
如果不是在同一个事务内锁数量超过阀值不会触发锁升级!
f
SELECT [resource_type] FROM sys.[dm_tran_locks]
[resource_type] 资源类型的值是之前描述过的锁定资源之一,资源类型后面括号内的数值是资源类型的代号
SR表示子资源subresource
数据1,数据2,数据3
ff
SR (subresource)
如果锁存在于一个数据库资源上,SR表示下列之一
完全数据库级锁
容量操作锁
如果锁存在于表资源上,SR表示下列之一
完全表级锁(默认)
更新统计锁
编译锁
如果锁存在于索引资源上,SR表示下列之一:
完全索引锁(默认)
索引ID锁
索引名字锁
f
锁拥有者块描述了一个会话拥有或者等待的每个锁,锁拥有者块的列表构成了授权,转换,等待列表,对锁块进行控制
f
除了sys.[dm_tran_locks]视图之外,还有另一个名为syslockinfo的元数据对象可以提供有关锁的内部信息,在引入sql2005的DMV之前,syslockinfo是唯一可用的内部元数据,事实上,存储过程sp_lock依然定义从syslockinfo表而不是sys.[dm_tran_locks]视图中获取信息
从1996年就有这个sp_lock存储过程
SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO create procedure sys.sp_lock --- 1996/04/08 00:00 @spid1 int = NULL, /* server process id to check for locks */ @spid2 int = NULL /* other process id to check for locks */ as set nocount on /* ** Show the locks for both parameters. */ set transaction isolation level read committed if @spid1 is not NULL begin select convert (smallint, req_spid) As spid, rsc_dbid As dbid, rsc_objid As ObjId, rsc_indid As IndId, substring (v.name, 1, 4) As Type, substring (rsc_text, 1, 32) as Resource, substring (u.name, 1, 8) As Mode, substring (x.name, 1, 5) As Status from master.dbo.syslockinfo, master.dbo.spt_values v, master.dbo.spt_values x, master.dbo.spt_values u where master.dbo.syslockinfo.rsc_type = v.number and v.type = 'LR' and master.dbo.syslockinfo.req_status = x.number and x.type = 'LS' and master.dbo.syslockinfo.req_mode + 1 = u.number and u.type = 'L' and req_spid in (@spid1, @spid2) end /* ** No parameters, so show all the locks. */ else begin select convert (smallint, req_spid) As spid, rsc_dbid As dbid, rsc_objid As ObjId, rsc_indid As IndId, substring (v.name, 1, 4) As Type, substring (rsc_text, 1, 32) as Resource, substring (u.name, 1, 8) As Mode, substring (x.name, 1, 5) As Status from master.dbo.syslockinfo, master.dbo.spt_values v, master.dbo.spt_values x, master.dbo.spt_values u where master.dbo.syslockinfo.rsc_type = v.number and v.type = 'LR' and master.dbo.syslockinfo.req_status = x.number and x.type = 'LS' and master.dbo.syslockinfo.req_mode + 1 = u.number and u.type = 'L' order by spid end return (0) -- sp_lock GO
SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO CREATE VIEW sys.syslockinfo AS SELECT * FROM OpenRowSet(SysLockInfo) GO
SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO CREATE VIEW sys.dm_tran_locks AS SELECT * FROM OpenRowSet(SysLockInformation) GO
master数据库中的syslockinfo表是可以用于观察的,其中一个字段rsc_bin(resource_binary),包含了16个字节长的对于被锁资源的描述
f
USE [AdventureWorks2008] SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO BEGIN TRAN SELECT * FROM [Person].[Address] WHERE [AddressID]=249 GO SELECT [rsc_bin],[rsc_type] FROM [master]..SYSLOCKINFO WHERE [rsc_type] IN(5,6,7)
[AdventureWorks]应该从sql2005才有的示例库
[rsc_bin]的最后两个字节是资源类型,因此经过字节交换后可以看到与[rsc_type]字段显示相同的值
例如 0xAFC61905000000000000000013000500 ,5
0500交换为0005,对应资源类型5(表级锁),倒数第二个双字节表示数据库ID,对于全部三行记录,该值经字节交换后是0013再转为十进制19(SELECT DB_ID('AdventureWorks2008')=19),也就是当前[AdventureWorks2008]数据库的ID
0xAFC61905000000000000000013000500 (rsc_type=5)
剩下的字节随着资源类型的不同而改变,对于表而言,前4个字节代表对象ID,第一条记录的对象锁(rsc_type=5)AFC61905经过字节交换后的值为0519C6AF,十进制就是85575343,再通过OBJECT_NAME转译,SELECT OBJECT_NAME(85575343)=Address
0x5C4F0000010000000000000013000600
对于页面类型rsc_type=6,前6个字节是文件号+页面号,经过字节交换,5C4F00000100字节交换 000100004F5C,文件号是0001(2个字节),页面号是00004F5C (4个字节)十进制20316 因此锁加在文件号1,页号为20316的页面上
0x560000000001CFF20B8173E513000700
rsc_type=7 前6个字节代表分区id 但是其转译过程需要一点技巧,在字节交换后还需要增加两个字节的0值 560000000001字节交换010000000056 加两个字节的0 0100000000560000 转为十进制72057594043564032
通过查询SELECT * FROM sys.[partitions] WHERE [partition_id]=72057594043564032
结果显示在表(85575343)的分区一上面
sqlserver利用哈希函数生成一个6字节长的哈希串来代表这个键,尽管无法对他进行逆向工程来确定究竟是哪些索引行被锁定住
6字节
f
绑定连接 SQL6.5就是通过绑定连接,令牌传递的方法来共享锁空间
绑定连接的两种方式:1、传递令牌bindtoken 2、MARS
EXEC [sys].[sp_getbindtoken] EXEC sys.[sp_bindsession]
f
共享锁空间和共享事务空间
--第一个查询窗口 session1 DECLARE @token VARCHAR(255) BEGIN TRAN EXEC [sys].[sp_getbindtoken] @token OUTPUT SELECT @token --a8M4EhRGJQ;4XZ<_E-Td<]5---/1G--- -------------------------- USE [AdventureWorks2008] BEGIN TRAN UPDATE [Production].[Product] SET [ListPrice]=180 WHERE [Name]='chain' ----------------------------- ROLLBACK TRAN 此会话中的活动事务已由另外一个会话提交或终止。 消息 3903,级别 16,状态 1,第 1 行 ROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION。
--第二个查询窗口 session2 EXEC [sys].[sp_bindsession] 'a8M4EhRGJQ;4XZ<_E-Td<]5---/1G---' -------------------------------- SELECT * FROM [Production].[Product] WHERE [Name]='chain' ------------------------------- ROLLBACK TRAN
这个令牌一定要人为传递
SELECT * FROM [sys].[dm_tran_session_transactions]
对能够绑定在一起的session并不存在技术上的限制,因此可以存在很多transaction_id相同的session
f
MARS的使用,在同一个tab里面select还没有执行完毕,可以再执行其他语句
当sqlserver7.0将页面大小从2KB变为8KB时,问题开始变得严重
f
使用闩来包含非叶级索引页面
EXEC [sys].[sp_dboption] @dbname = NULL, -- sysname
@optname = '', -- varchar(35)
@optvalue = '' -- varchar(10)
手动控制锁定单位,禁止索引内使用页锁或者行锁,对于堆是没有办法控制锁定单位的
建表时,如果allowrowlocks 和allowpagelocks被设置off,那么只有表锁
f
如果锁升级以后,存在锁冲突,那么升级尝试可能会失败
sqlserver绝对不会将锁升级为页锁,而且也不可能只锁定表或索引的一个单独分区,锁升级的结果总是会锁定一个完全表锁,表分区的话锁定所有分区
sqlserver达到多少锁进行升级
sqlserver是无法对锁进行降级的!!
跟踪标志1211完全禁用锁升级
f
跟踪标志1224 基于已获得锁的数量来禁用锁升级,没有1211那么激进
如果两个跟踪标志都设置了,1211会优先于1224
sqlserver中有两种主要类型的死锁可能发生,循环死锁(cycle deadlock) 转换死锁(conversion deadlock)
f
f
死锁侦测不会用到闩,因为当获取闩的时候,sqlserver会使用防止死锁(deadlock-proof)的算法
lockmonitor的线程每隔5秒检查一次系统的死锁情况,当死锁发生时,死锁侦测间隔会减少到100毫秒一次,如果死锁频率降低了,该间隔又会降到5秒一次
f
如果会话进行事务回滚,那么这个会话不会被选作死锁牺牲者,因为被回滚的那些更改可能会进入不确定的状态,导致数据损坏 (data corruption)
闩锁和自旋锁没有死锁侦测服务
f
f
当一行被更新时,sqlserver使用XSN事务序列号来标记新的行,XSN是一个单调增长的数字,在每个sqlserver实例中保证唯一,XSN是sqlserver2005中新引入的概念,他不同于lsn
xsn号,全称xact sequence number
之前版本存储在tempdb中,新的行包含一个指向版本存储区中的旧行的一个指针,版本存储区里旧行数据可能包含指向更早版本的指针,一条行记录的所有版本被串接到一个链接列表中,sqlserver可能需要沿着链表中的几个指针才能达到一个正确的版本,只要有操作需要引用他们,行版本就必须在版本存储区内保留
f
http://www.cnblogs.com/MYSQLZOUQI/articles/3911287.html
从微观上来说,写写串行就是一个不能并行写入的一个例子,从宏观来说,sqlserver的对等复制,mysql的双master
就是不能并行写入的例子,所以,无论宏观还是微观,写入都是不可能并行的,否则就会发生冲突
后续写着重新提交初始请求,oracle也是一样,写写串行
然而任何好处都必须有代价,不是吗?你所付出的代价就是所谓的写写串行。没错,写被严格串行了。记住,尽管你可以读取数据的任意历史版本,但写只会作用于数据的当前版本,或者叫最新版本。所谓写写串行,就是说如果在你开始事务和写数据之间,数据已经被其它人改了,或者说的准确点,当你看到的版本不是当前版本时,You Have Been Killed(事务回滚)。所以你会注意到,ORACLE本质上并不适合于写写冲突剧烈的应用(听到这,DB2或SQL Server们笑了)。
1、已提交读快照隔离级别:只需要开启数据库的一个选项即可 ALTER DATABASE [AdventureWorks2008] SET READ_COMMITTED_SNAPSHOT
2、快照隔离级别:需要开启数据库选项ALTER DATABASE [AdventureWorks2008] SET ALLOW_SNAPSHOT_ISOLATION ,
然后通过每个session的SET TRANSACTION ISOLATION LEVEL SNAPSHOT为每个会话开启si隔离级别
f
ALTER DATABASE [AdventureWorks2008] SET READ_COMMITTED_SNAPSHOT ON WITH NO_WAIT
或者
ALTER DATABASE [AdventureWorks2008] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
可以使用 WITH NO_WAIT来设置已提交读快照隔离级别
f
IN_TRANSACTION_TO_ON
IN_TRANSACTION_TO_OFF
f
f
观察数据库的状态
SELECT DB_NAME([database_id]) , [snapshot_isolation_state] , [snapshot_isolation_state_desc], [is_read_committed_snapshot_on] FROM SYS.[databases]
F
更新冲突只可能发生是快照隔离级别,而不可能发生已提交读快照隔离级别,因为快照隔离级别是基于事务而不是基于语句的
F
F
f
快照隔离级别下,下面的DDL是被禁止的
create/alter/drop index
dbcc dbreindex
alter table
alter partition function/schema
f
f
另一个数据库没有开启版本控制依然可以跨库访问
ALTER DATABASE [AdventureWorks2008] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE USE [AdventureWorks2008] SELECT * FROM [sss].[dbo].[testrow]
f
f
f
查询行版本数据
SELECT DB_NAME([database_id]) AS dbname,* FROM [sys].[dm_tran_version_store]
为了支持行版本,一个数据行需要额外的14个字节来跟踪这些指针的信息,其他的8个字节是为tempdb的文件、页面、行实际指针准备,
而剩下的6个字节用来存储XSN以帮助sqlserver确定哪些行是当前的,哪些行版本是一个特定事务需要访问的。当介绍一些其他的快照事务元数据时,还会进一步讨论xsn
其中状态A为如下说明:
bit0:版本信息,在SQL Server 2005/08总是为0 ,如果为1,即开启了快照隔离级别,存储行版本
bit1-3: 0=(primary record);1=(forwarded record);2=(forwarding stud);3=(index record);4=(溢出数据);5=(ghost索引记录);6=(ghost数据记录)
bit4:表示存在NULL位图(在数据行里SQL2005/08总存在NULL位图)
bit5:表示存在变长列
bit6:未启用
bit7:表示存在幽灵记录
f
快照隔离级别用于造成页拆分,因为insert的时候还没有14个字节数据,当update的时候添加了14个字节的数据,那么就容易造成原来页面容纳不下,需要页拆分
SELECT [version_ghost_record_count] , [ghost_record_count] FROM SYS.[dm_db_index_physical_stats](DB_ID(), NULL, NULL, NULL, NULL) 包含了鬼影记录数和鬼影记录总数
一旦改变了数据库选项,每当有版本信息的行被更新时,有关版本控制的字节就会移除掉
f
清理版本信息的进程每分钟在后台进行一次
用性能计数器实时检测tempdb
f
ALTER DATABASE [sss] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE USE [sss] CREATE TABLE T1(T1ID CHAR(1),T1name CHAR(10)) GO INSERT T1 SELECT 'A','aaa' INSERT T1 SELECT 'B','bbb' GO DBCC IND([sss],'T1',-1) --89 DBCC TRACEON(3604) DBCC PAGE('SSS',1,89,1) UPDATE T1 SET T1name='222' WHERE T1ID='A' DBCC TRACEON(3604) DBCC PAGE('SSS',1,89,1) DELETE FROM T1 WHERE T1ID='A' DBCC TRACEON(3604) DBCC PAGE('SSS',1,89,1) ---------------------------------------------------------------- Page @0x000000008998A000 m_pageId = (1:89) m_headerVersion = 1 m_type = 1 m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0xa000 m_objId (AllocUnitId.idObj) = 30 m_indexId (AllocUnitId.idInd) = 256 Metadata: AllocUnitId = 72057594039894016 Metadata: PartitionId = 72057594038845440 Metadata: IndexId = 0 Metadata: ObjectId = 2121058592 m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 15 m_slotCnt = 2 m_freeCnt = 8028 m_freeData = 160 m_reservedCnt = 0 m_lsn = (36:185:2) m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 0 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED DATA: Slot 0, Offset 0x60, Length 32, DumpStyle BYTE Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VERSIONING_INFO Record Size = 32 7个字节行头信息+1+10 char类型数据+14个字节的行版本=32字节 Memory Dump @0x000000000FAEA060 0000000000000000: 50000f00 41616161 20202020 20202002 †P...Aaaa . 0000000000000010: 00000000 00000000 0000e00f 00000000 †................ 50 翻转 05 二进制 00000101 0000e10f 00000000 0000 00000000 0000e10f 00000000 ----------------------------------------------------------------------- Slot 0, Offset 0xa0, Length 15, DumpStyle BYTE Record Type = GHOST_VERSION_RECORD Record Attributes = VERSIONING_INFO Record Size = 15 Memory Dump @0x000000000D39A0A0 0000000000000000: 4ef00100 00010006 000d1100 000000††††N..............
SELECT * FROM sys.[dm_tran_version_store] SELECT * FROM sys.[dm_tran_transactions_snapshot] SELECT * FROM sys.[dm_tran_active_snapshot_database_transactions]
这些视图全部都包含一个[transaction_sequence_num]字段也就之前说的XSN值
事务id值是跨整个服务器,针对每个事务增长的,这其中包括系统事务,因此无论该事务是否与任何快照操作相关,当前事务id值通常远远大于当前的xsn值
可以使用SELECT * FROM sys.[dm_tran_current_transaction]视图来检查当前事务的数值信息
SELECT * FROM sys.[dm_tran_current_transaction]
F
F
sys.[dm_tran_active_snapshot_database_transactions]和 sys.[dm_exec_sessions] 进行连接得到快照信息 SELECT [transaction_sequence_num] , [commit_sequence_num] , [is_snapshot] , t.[session_id] , [first_snapshot_sequence_num] , [max_version_chain_traversed] , [elapsed_time_seconds] , [host_name] , [login_time] , [transaction_isolation_level] FROM sys.[dm_tran_active_snapshot_database_transactions] t JOIN sys.[dm_exec_sessions] s ON t.[session_id] = s.[session_id]
f
sys.[dm_tran_active_snapshot_database_transactions]和 sys.[dm_exec_sessions]
进行连接得到快照信息
SELECT [max_version_chain_traversed]
FROM sys.[dm_tran_active_snapshot_database_transactions] t
JOIN sys.[dm_exec_sessions] s ON t.[session_id] = s.[session_id]
[max_version_chain_traversed]当一个读事务读取记录的时候,不停有更新事务更新记录,那么[max_version_chain_traversed]字段就会不断增长,这种增长是使用快照隔离的一种额外开销,在快照事务需要的数据上执行更多的更新操作时,读操作就需要更长的时间,因为sqlserver必须遍历一个更长的版本链来获取事务所需的数据
f
F
触发器,mars,联机索引使用行版本
sqlserver的早起版本通过扫描事务日志,并查找修改绑定了触发器的表的当前所有事务日志记录,来构建这些伪表
F
MARS作为绑定连接的替代品
F
F
SQLSERVER的锁提示能够覆盖会话当前的事务隔离级别
F
F
设置锁超时
只对当前连接有效 超时值设置为5秒
SET LOCK_TIMEOUT 5000
SELECT @@LOCK_TIMEOUT
F
F
F
如果数据库中出现数据被锁的问题后,对应的数据就无法再操作了,那么我们要怎么查看数据库中的锁信息,以找出对应的解决方法呢?
方法一:在microsoft sql server management studio中打开"管理"->"sql server日志"中查看日志信息
方法二:利用系统表syslockinfo查看锁信息。
查看SQL语句如下:
--查看数据库中锁信息 create table #tableable(req_spid int,obj_name sysname) declare @s nvarchar(4000), @rid int,@dbname sysname, @id int,@objname sysname declare tb cursor for select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid from master..syslockinfo where rsc_type in(4,5) open tb fetch next from tb into @rid,@dbname,@id while @@fetch_status=0 begin set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id' exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id insert into #table values(@rid,@objname) fetch next from tb into @rid,@dbname,@id end close tb deallocate tb select 进程id=a.req_spid, 数据库=db_name(rsc_dbid), 资源类型=case rsc_type when 1 then 'NULL 资源(未使用)' when 2 then '数据库' when 3 then '文件' when 4 then '索引' when 5 then '表' when 6 then '页' when 7 then '键' when 8 then '扩展盘区' when 9 then 'RID(行 ID)' when 10 then '应用程序' end ,对象id=rsc_objid ,对象名=b.obj_name ,rsc_indid from master..syslockinfo a left join #tableable b on a.req_spid=b.req_spid go drop table #tableable
大家可以修改上面的SQL语句,以查询出自己所需的信息。
下面是对系统表syslockinfo中列的解释:
列名 说明
rsc_text 锁资源的文本化描述。包含资源名称的一部分。
rsc_bin 二进制锁资源。包含锁管理器中所含的实际锁资源。对那些了解锁资源格式的工具包含该列,这些工具可生成自己的格式化锁资源并在 syslockinfo 上执行自联接。
rsc_valblk 锁值块。有些资源类型可以在特定的锁资源中包含附加数据,锁管理器不对这类锁资源进行哈希运算以决定具体某个锁资源的所有关系。例如,页锁不归具体的对象 ID 所有。但是,对于锁升级和出于其他目的,页锁的对象 ID 可以包括在锁值块中。
rsc_dbid 与资源关联的数据库 ID。
rsc_indid 与资源关联的索引 ID(如果适合)。
rsc_objid 与资源关联的对象 ID(如果适合)。
rsc_type 资源类型:
1 = NULL 资源(未使用)
2 = 数据库
3 = 文件
4 = 索引
5 = 表
6 = 页
7 = 键
8 = 区
9 = RID(行 ID)
10 = 应用程序
rsc_flag 内部资源标志。
req_mode 锁请求模式。该列是请求者的锁模式,并且代表已授权模式,或代表转换或等待模式。
0 = NULL。不授权访问资源。用作占位符。
1 = Sch-S(架构稳定性)。确保在任何会话持有对架构元素(例如表或索引)的架构稳定性锁时,不删除该架构元素。
2 = Sch-S(架构修改)。必须由要更改指定资源架构的任何会话持有。确保没有其他会话正在引用所指示的对象。
3 = S(共享)。授予持有锁的会话对资源的共享访问权限。
4 = U(更新)。指示对最终可能更新的资源获取的更新锁。用于防止常见形式的死锁,这类死锁在多个会话锁定资源并且稍后可能更新资源时发生。
5 = X(排他)。授予持有锁的会话对资源的独占访问权限。
6 = IS(意向共享)。指示有意将 S 锁放置在锁层次结构中的某个从属资源上。
7 = IU(意向更新)。指示有意将 U 锁放置在锁层次结构中的某个从属资源上。
8 = IX(意向排他)。指示有意将 X 锁放置在锁层次结构中的某个从属资源上。
9 = IU(共享意向更新)。指示对有意在锁层次结构中的从属资源上获取更新锁的资源进行共享访问。
10 = IX(共享意向排他)。指示对有意在锁层次结构中的从属资源上获取排他锁的资源进行共享访问。
11 = IX(更新意向排他)。指示对有意在锁层次结构中的从属资源上获取排他锁的资源持有的更新锁。
12 = BU。由大容量操作使用。
13 = RangeS_S(共享键范围和共享资源锁)。指示可串行范围扫描。
14 = RangeS_U(共享键范围和更新资源锁)。指示可串行更新扫描。
5 = RangeI_N(插入键范围和空资源锁)。用于在将新键插入索引前测试范围。
16 = RangeI_S。通过 RangeI_N 和 S 锁的重叠创建的键范围转换锁。
17 = RangeI_U。通过 RangeI_N 和 U 锁的重叠创建的键范围转换锁。
18 = RangeI_X。通过 RangeI_N 和 X 锁的重叠创建的键范围转换锁。
19 = RangeX_S。通过 RangeI_N 和 RangeS_S 锁的重叠创建的键范围转换锁。
20 = RangeX_U。通过 RangeI_N 和 RangeS_U 锁的重叠创建的键范围转换锁。
21 = RangeX_X(排他键范围和排他资源锁)。这是在更新范围中的键时使用的转换锁。
req_status 锁请求的状态:
1 = 已授予
2 = 正在转换
3 = 正在等待
req_refcnt 锁引用计数。事务每次请求具体某个资源上的锁时,引用计数便会增加。直到引用计数等于 0 时才能释放锁。
req_cryrefcnt 保留以供将来使用。总是设置为 0。
req_lifetime 锁生存期位图。在某些查询处理策略的过程中,必须维护资源上的锁,直到查询处理器已完成查询的某个具体阶段为止。查询处理器和事务管理器用锁生存期位图指示在查询结束运行的某个阶段时可以释放的锁组。位图内的某些位用于指示即使锁的引用计数等于 0,也必须到事务结束时才释放的锁。
req_spid 请求锁的会话的内部 Microsoft SQL Server Database Engine?进程 ID。
req_ecid 执行上下文 ID (ECID)。用于指示并行操作内拥有具体某个锁的线程。
req_ownertype 与锁关联的对象类型:
1 = 事务
2 = 游标
3 = 会话
4 = ExSession
注意,3 和 4 代表会话锁的特殊版本,分别跟踪数据库锁和文件组锁。
req_transactionID 用于 syslockinfo 和事件探查器事件中的唯一事务 ID。
req_transactionUOW 标识 DTC 事务的工作单元 ID (UOW)。对于非 MS DTC 事务,UOW 设置为 0。
注意:在SQL 2005及以上的版本中,推荐用sys.dm_tran_locks来代替syslockinfo系统表。
http://www.lmwlove.com/ac/id696
测试sys.[dm_exec_requests]视图的对象锁 OBJECT: 8:5575058:0
脚本
USE [sss] --只有聚集索引 CREATE TABLE Department ( DepartmentID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY , Name NVARCHAR(200) NOT NULL , GroupName NVARCHAR(200) NOT NULL , Company NVARCHAR(300) , ModifiedDate DATETIME NOT NULL DEFAULT ( GETDATE() ) ) INSERT INTO Department(name,[Company],groupname) VALUES('销售部','中国你好有限公司XX分公司','销售组') GO 1000 USE [sss] GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO --以下查询使用了聚集索引查找 ctrl+l BEGIN TRAN SELECT GroupName FROM [dbo].[Department] WHERE DepartmentID IN ( 641, 361, 281 ) --COMMIT TRAN USE [sss] --要查询申请锁的数据库 GO SELECT [request_session_id] , c.[program_name] , DB_NAME(c.[dbid]) AS dbname , [resource_type] , [request_status] , [request_mode] , [resource_description] , OBJECT_NAME(p.[object_id]) AS objectname , p.[index_id] FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p ON a.[resource_associated_entity_id] = p.[hobt_id] LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id] = c.[spid] WHERE c.[dbid] = DB_ID('sss') AND a.[request_session_id] = @@SPID ----要查询申请锁的数据库 ORDER BY [request_session_id] , [resource_type] SELECT * FROM sys.[dm_exec_requests] WHERE [session_id]=@@SPID ROLLBACK TRAN ------------------------------------------------- USE [sss] GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO --以下查询使用了聚集索引查找 ctrl+l BEGIN TRAN UPDATE [Department] SET GroupName='sdfsd' WHERE [DepartmentID]=641 --COMMIT TRAN USE [sss] --要查询申请锁的数据库 GO SELECT [request_session_id], c.[program_name], DB_NAME(c.[dbid]) AS dbname, [resource_type], [request_status], [request_mode], [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, p.[index_id] FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p ON a.[resource_associated_entity_id]=p.[hobt_id] LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] WHERE c.[dbid]=DB_ID('sss') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 ORDER BY [request_session_id],[resource_type] SELECT * FROM sys.[dm_exec_requests] WHERE [session_id]=@@SPID ROLLBACK TRAN -----------------------------------------------------------------
USE [sss] GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO --以下查询使用了聚集索引查找 ctrl+l BEGIN TRAN DELETE FROM [Department] WHERE [DepartmentID]=2 --COMMIT TRAN USE [sss] --要查询申请锁的数据库 GO SELECT [request_session_id], c.[program_name], DB_NAME(c.[dbid]) AS dbname, [resource_type], [request_status], [request_mode], [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, p.[index_id] FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p ON a.[resource_associated_entity_id]=p.[hobt_id] LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] WHERE c.[dbid]=DB_ID('sss') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 ORDER BY [request_session_id],[resource_type] SELECT [wait_resource] FROM sys.[dm_exec_requests] WHERE [session_id]=@@SPID --ROLLBACK TRAN
存储过程
CREATE PROCEDURE [dbo].[wdwfinglock] AS SELECT S.session_id, R.blocking_session_id, S.host_name, S.login_name, S.program_name, S.status, S.cpu_time, memory_usage_kb = S.memory_usage * 8, S.reads, S.writes, S.transaction_isolation_level, C.connect_time, C.last_read, C.last_write, C.net_transport, C.client_net_address, C.client_tcp_port, C.local_tcp_port, R.start_time, R.command, R.status, R.wait_time, R.wait_type, R.last_wait_type, R.wait_resource, R.open_transaction_count, R.transaction_id, current_execute_sql = SUBSTRING(T.text, R.statement_start_offset / 2 + 1, CASE WHEN statement_end_offset = -1 THEN LEN(T.text) ELSE (R.statement_end_offset - statement_start_offset) / 2+1 END) FROM sys.dm_exec_sessions S LEFT JOIN sys.dm_exec_connections C ON S.session_id = C.session_id LEFT JOIN sys.dm_exec_requests R ON S.session_id = R.session_id AND C.connection_id = R.connection_id OUTER APPLY sys.dm_exec_sql_text(R.sql_handle) T WHERE S.is_user_process = 1 and R.blocking_session_id is not null and R.blocking_session_id<>0 -- 如果不限制此条件,则查询所有进程(系统和用户进程)
USE [sss] GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO --以下查询使用了聚集索引查找 ctrl+l BEGIN TRAN DROP TABLE [Department] --COMMIT TRAN USE [sss] --要查询申请锁的数据库 GO SELECT [request_session_id], c.[program_name], DB_NAME(c.[dbid]) AS dbname, [resource_type], [request_status], [request_mode], [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, p.[index_id] FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p ON a.[resource_associated_entity_id]=p.[hobt_id] LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] WHERE c.[dbid]=DB_ID('sss') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 ORDER BY [request_session_id],[resource_type] SELECT [wait_resource] FROM sys.[dm_exec_requests] WHERE [session_id]=@@SPID --ROLLBACK TRAN
SELECT * FROM sys.[dm_tran_locks] SELECT * FROM sys.[dm_exec_requests] WHERE [session_id]=66 --OBJECT: 8:5575058:0 SELECT DB_ID('sss')=8 SELECT OBJECT_ID('Department')=5575058
http://social.technet.microsoft.com/Forums/zh-CN/2fc600dc-9035-40d4-ae0d-19dad888a30b/object?forum=sqlserverzhchs
地方
CREATE INDEX idx_Department_ModifiedDate ON [Department]([ModifiedDate])
USE [sss] GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO --以下查询使用了聚集索引查找 ctrl+l BEGIN TRAN UPDATE [Department] SET GroupName='sdfsd' WHERE [ModifiedDate]='2014-09-16 10:12:05.213' --COMMIT TRAN USE [sss] --要查询申请锁的数据库 GO SELECT [request_session_id], c.[program_name], DB_NAME(c.[dbid]) AS dbname, [resource_type], [request_status], [request_mode], [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, p.[index_id] FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p ON a.[resource_associated_entity_id]=p.[hobt_id] LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] WHERE c.[dbid]=DB_ID('sss') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 ORDER BY [request_session_id],[resource_type] SELECT * FROM sys.[dm_exec_requests] WHERE [session_id]=@@SPID --ROLLBACK TRAN
USE [sss] GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO --以下查询使用了聚集索引查找 ctrl+l BEGIN TRAN DROP TABLE [Department] --COMMIT TRAN USE [sss] --要查询申请锁的数据库 GO SELECT [request_session_id], c.[program_name], DB_NAME(c.[dbid]) AS dbname, [resource_type], [request_status], [request_mode], [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, p.[index_id] FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p ON a.[resource_associated_entity_id]=p.[hobt_id] LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] WHERE c.[dbid]=DB_ID('sss') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 ORDER BY [request_session_id],[resource_type] SELECT [wait_resource] FROM sys.[dm_exec_requests] WHERE [session_id]=@@SPID --ROLLBACK TRAN
SELECT * FROM sys.[dm_tran_locks] WHERE [request_session_id]=64 SELECT * FROM sys.[dm_exec_requests] WHERE [session_id]=64 --OBJECT: 8:5575058:0 SELECT DB_ID('sss')=8 SELECT OBJECT_ID('Department')=5575058 EXEC [sys].[sp_lock] @spid1 = 66 SELECT [session_id],[wait_resource] FROM sys.[dm_exec_requests] 最后一个字符是indid OBJECT: 8:5575058:0 dbid,objid,indid
http://msdn.microsoft.com/zh-cn/library/ms187749(v=SQL.100).aspx
在 sp_lock 结果集中,由 @spid1 和 @spid2 参数指定的会话所持有的每个锁都对应一行。如果既未指定 @spid1 又未指定 @spid2,则结果集将报告当前在数据库引擎实例中处于活动状态的所有会话的锁。
列名 |
数据类型 |
说明 |
---|---|---|
spid |
smallint |
请求锁的进程的数据库引擎会话 ID 号。 |
dbid |
smallint |
保留锁的数据库的标识号。可以使用 DB_NAME() 函数来标识数据库。 |
ObjId |
int |
持有锁的对象的标识号。可以在相关数据库中使用 OBJECT_NAME() 函数来标识对象。值为 99 时是一种特殊情况,表示用于记录数据库中页分配的其中一个系统页的锁。 |
IndId |
smallint |
持有锁的索引的标识号。 |
Type |
nchar(4) |
锁的类型: RID = 表中单个行的锁,由行标识符 (RID) 标识。 KEY = 索引内保护可串行事务中一系列键的锁。 PAG = 数据页或索引页的锁。 EXT = 对某区的锁。 TAB = 整个表(包括所有数据和索引)的锁。 DB = 数据库的锁。 FIL = 数据库文件的锁。 APP = 指定的应用程序资源的锁。 MD = 元数据或目录信息的锁。 HBT = 堆或 B 树索引的锁。在 SQL Server 中此信息不完整。 AU = 分配单元的锁。在 SQL Server 中此信息不完整。 |
Resource |
nchar(32) |
标识被锁定资源的值。值的格式取决于 Type 列标识的资源类型: Type 值:Resource 值 RID:格式为 fileid:pagenumber:rid 的标识符,其中 fileid 标识包含页的文件,pagenumber 标识包含行的页,rid 标识页上的特定行。fileid 与 sys.database_files 目录视图中的file_id 列相匹配。 KEY:数据库引擎内部使用的十六进制数。 PAG:格式为 fileid:pagenumber 的数字,其中 fileid 标识包含页的文件,pagenumber 标识页。 EXT:标识区中的第一页的数字。该数字的格式为 fileid:pagenumber。 TAB:没有提供信息,因为已在 ObjId 列中标识了表。 DB:没有提供信息,因为已在 dbid 列中标识了数据库。 FIL:文件的标识符,与 sys.database_files 目录视图中的 file_id 列相匹配。 APP:被锁定的应用程序资源的唯一标识符。格式为 DbPrincipleId:<资源字符串的前 2 个到 16 个字符><哈希运算值>。 MD:随资源类型而变化。有关详细信息,请参阅 sys.dm_tran_locks (Transact-SQL) 中 resource_description 列的说明。 HBT:没有提供任何信息。请改用 sys.dm_tran_locks 动态管理视图。 AU:没有提供任何信息。请改用 sys.dm_tran_locks 动态管理视图。 |
模式 |
nvarchar(8) |
所请求的锁模式。可以是: NULL = 不授予对资源的访问权限。用作占位符。 Sch-S = 架构稳定性。确保在任何会话持有对架构元素(例如表或索引)的架构稳定性锁时,不删除该架构元素。 Sch-M = 架构修改。必须由要更改指定资源架构的任何会话持有。确保没有其他会话正在引用所指示的对象。 S = 共享。授予持有锁的会话对资源的共享访问权限。 U = 更新。指示对最终可能更新的资源获取的更新锁。用于防止一种常见的死锁,这种死锁在多个会话锁定资源以便稍后对资源进行更新时发生。 X = 排他。授予持有锁的会话对资源的独占访问权限。 IS = 意向共享。指示有意将 S 锁放置在锁层次结构中的某个从属资源上。 IU = 意向更新。指示有意将 U 锁放置在锁层次结构中的某个从属资源上。 IX = 意向排他。指示有意将 X 锁放置在锁层次结构中的某个从属资源上。 SIU = 共享意向更新。指示对有意在锁层次结构中的从属资源上获取更新锁的资源进行共享访问。 SIX = 共享意向排他。指示对有意在锁层次结构中的从属资源上获取排他锁的资源进行共享访问。 UIX = 更新意向排他。指示对有意在锁层次结构中的从属资源上获取排他锁的资源持有的更新锁。 BU = 大容量更新。用于大容量操作。 RangeS_S = 共享键范围和共享资源锁。指示可串行范围扫描。 RangeS_U = 共享键范围和更新资源锁。指示可串行更新扫描。 RangeI_N = 插入键范围和 Null 资源锁。用于在将新键插入索引前测试范围。 RangeI_S = 键范围转换锁。由 RangeI_N 和 S 锁的重叠创建。 RangeI_U = 由 RangeI_N 和 U 锁的重叠创建的键范围转换锁。 RangeI_X = 由 RangeI_N 和 X 锁的重叠创建的键范围转换锁。 RangeX_S = 由 RangeI_N 和 RangeS_S 锁的重叠创建的键范围转换锁。 RangeX_U = 由 RangeI_N 和 RangeS_U 锁的重叠创建的键范围转换锁。 RangeX_X = 排他键范围和排他资源锁。这是在更新范围中的键时使用的转换锁。 |
Status |
nvarchar(5) |
锁的请求状态: CNVRT:锁正在从另一种模式进行转换,但是转换被另一个持有锁(模式相冲突)的进程阻塞。 GRANT:已获取锁。 WAIT:锁被另一个持有锁(模式相冲突)的进程阻塞。 |
地方
http://social.msdn.microsoft.com/Forums/zh-CN/2fc600dc-9035-40d4-ae0d-19dad888a30b/object?forum=sqlserverzhchs
SELECT * FROM sys.[dm_tran_locks] WHERE [request_session_id]=64 SELECT * FROM sys.[dm_exec_requests] WHERE [session_id]=66 SELECT [rsc_bin] , [rsc_type] FROM [master]..SYSLOCKINFO AS syslock JOIN sys.[dm_exec_requests] AS req ON [req].[session_id] = [syslock].[req_spid] rsc_type tinyint 资源类型。可以是: 1 = NULL 资源(未使用)。 2 = 数据库。 3 = 文件。 4 = 索引。 5 = 表。 6 = 页。 7 = 键。 8 = 扩展盘区。 9 = RID(行 ID)。 10 = 应用程序。 rsc_bin rsc_type 0x00000000000000000000000008000200 2 0x00000000000000000000000008000200 2 0x92115500000000000000000008000500 5 rsc_bin]的最后两个字节是资源类型,因此经过字节交换后可以看到与[rsc_type]字段显示相同的值 例如 0xAFC61905000000000000000013000500 ,5 0500交换为0005,对应资源类型5(表级锁),倒数第二个双字节表示数据库ID,对于全部三行记录,该值经字节交换后是0013再转为十进制19(SELECT DB_ID('AdventureWorks2008')=19),也就是当前[AdventureWorks2008]数据库的ID 0xAFC61905000000000000000013000500 (rsc_type=5) 剩下的字节随着资源类型的不同而改变,对于表而言,前4个字节代表对象ID,第一条记录的对象锁(rsc_type=5)AFC61905经过字节交换后的值为0519C6AF,十进制就是85575343,再通过OBJECT_NAME转译,SELECT OBJECT_NAME(85575343)=Address 92115500:字节交换后:00551192 十进制就是5575058 再经过OBJECT_NAME转译,SELECT OBJECT_NAME(5575058)=Department表 --OBJECT: 8:5575058:0 SELECT DB_ID('sss')=8 SELECT OBJECT_ID('Department')=5575058 EXEC [sys].[sp_lock] @spid1 = 66 SELECT [session_id],[wait_resource] FROM sys.[dm_exec_requests] 最后一个字符是indid OBJECT: 8:5575058:0 dbid,objid,indid
最后一个数字代表resource_lock_partition的意思
SELECT REQ.wait_resource, wait_resource1 = 'OBJECT: ' + RTRIM(L.resource_database_id) + ':' + RTRIM(L.resource_associated_entity_id) + ':' + RTRIM(l.resource_lock_partition), * FROM sys.dm_exec_requests REQ OUTER APPLY( SELECT * FROM sys.dm_tran_locks LL WHERE LL.request_session_id = REQ.session_id AND LL.request_status = 'WAIT' AND LL.resource_type = 'OBJECT' ) L WHERE session_id > 50 AND wait_resource LIKE N'OBJECT:%'
df
SQLSERVER里存在三种表
1、系统表 元数据
2、基本表 简称基表
3、隐藏表 service broker 更改跟踪