SQL Server读提交快照隔离级别的注意事项

翻译 2017年09月18日 22:36:18

前言


当数据库中存在大量面积LCK_M_S 共享锁的时候,我们经常会选择使用读提交快照隔离级别,来解决阻塞的问题.但是所有技术都是使用场景的。在下面的场景下,使用读提交快照,就可能出现错误。

正文


从SQL Server 2005开始,我们就有了READ COMMITTED SNAPSHOT隔离级别(RCSI)和快照隔离级别(SI)。当使用这些新的隔离级别时,SELECT语句在阅读过程中不会获得S共享锁。 (UPDATE,DELETE语句)将他们正在更改的记录的旧版本,存入为TempDb。 他们正在创建一个版本链,其中记录的实际版本(存储在数据库中的数据页面上)指向存储在TempDb页面上的旧版本。 下图显示了这个概念。



为了实现上面的功能,SQL Server必须为数据库中的数据页面上的每个记录添加一个14字节长的指针。 这意味着每个记录的长度将延长14字节。 您可能已经知道,当您使用固定长度的数据类型时,SQL Server中的记录不能超过8060字节。 这意味着启用RCSI / SI可能导致这些记录大于8060字节。 让我们来看一个非常简单的例子
USE master
GO
 
-- Create a new database
CREATE DATABASE VersionStoreRestrictions
GO
 
-- Enable RCSI
ALTER DATABASE VersionStoreRestrictions SET READ_COMMITTED_SNAPSHOT ON
GO
 
-- Use it
USE VersionStoreRestrictions
GO
 
-- Create a table where each record is 8047 bytes large
CREATE TABLE TableB
(
   Column1 CHAR(40),
   Column2 CHAR(8000)
)
GO



从前面的代码中可以看到,我创建了一个表CHAR类型,加起来长度为8040字节。对于每个记录,SQL Server内部需要至少7个字节的开销。在这种情况下,一行记录需要8047字节的数据页。因为我们在数据库级别上启用了RCSI,所以SQL Server必须为行版本指针添加额外的14个字节,将表中的每个记录扩展到8061个字节。这意味着每个记录对都会超出SQL Server 规定的8060 (1 byte)
首先,我们将一个记录插入到表格中
-- Insert a initial row
INSERT INTO TableB VALUES (REPLICATE('A', 40), REPLICATE('A', 8000))
GO




然后,执行下面的update
UPDATE TableB
SET Column1 = REPLICATE('B', 40)
GO
Msg682,Level22,State214,Line2
Internalerror.Bufferprovidedtoreadcolumnvalueistoosmall.RunDBCCCHECKDBtocheckforanycorruption.

是一个内部错误,因为SQL Server使用的缓冲区只有8060字节大,现在我们尝试存储在缓冲区8061字节 - SQL Server 2008上还可以重现。 有趣的是,SQL Server Denali CTP1(就是SQL Server 2012)已经修复了这个错误,其中页面转储显示SQL Server存储预期的8061字节。
当您为现有数据库启用RCSI / SI时,请记住这个错误,因为这意味着RCSI / SI不是在任何场景都适用。 当您的数据库中有一个超过8046字节限制的表格时,您将遇到真正的麻烦

总结

除了上述问题,读提交快照还会增加tempdb的压力。这也是需要考虑的一个因素。

如何修改数据库的快照隔离级别

背景说明: 经常接到现场反馈,执行K/3 Cloud某个功能时,系统卡死。 此时连接到SQL Server数据库,执行如下SQL语句搜索数据库的进程,发现有明显的阻塞 -- 检查死锁...
  • fyq891014
  • fyq891014
  • 2016年04月27日 12:59
  • 1374

SQL Server 中的事务与事务隔离级别以及脏读

原 本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫。所以花了点时间,把 SQL Server ...
  • MaoTongBin
  • MaoTongBin
  • 2016年01月28日 15:04
  • 2719

SqlServer 并发事务(一):事务隔离级别

--查了当前数据库是事务隔离级别 DBCC USEROPTIONS 【测试一:丢失更新】 --事务1 begin tran select * from dbo.Test(nolock) wher...
  • kk185800961
  • kk185800961
  • 2014年11月26日 13:35
  • 11010

SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因...
  • csl127087
  • csl127087
  • 2015年07月10日 10:12
  • 497

SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因 原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需...
  • hbtianmimi
  • hbtianmimi
  • 2014年06月23日 15:08
  • 1111

【SQL Server】可重复读隔离级别里的可能死锁

可重复读隔离级别里的可能死锁 在今天的文章里我想谈论下在可重复读隔离级别(Transaction Isolation Level Repeatable Read)里,当你运行事务时可能引起的...
  • zhangzeyuaaa
  • zhangzeyuaaa
  • 2017年05月22日 00:30
  • 352

SQL Server事务、隔离级别详解(二十九)

前言 事务一直以来是我最薄弱的环节,也是我打算重新学习SQL Server的出发点,关于SQL Server中事务将分为几节来进行阐述,Always to review the basics。  ...
  • muzili12a3
  • muzili12a3
  • 2017年01月30日 10:18
  • 519

SQL Server 2005事务隔离级别与性能

转自:http://blog.sina.com.cn/s/blog_70b2dd760100lrgk.html 众所周知,SQL Server事务隔离级别是为了保证在并发事务处理环境...
  • lzlxyq
  • lzlxyq
  • 2013年09月26日 20:31
  • 937

SQL Server-字字珠玑,一纸详文,完全理解SERIALIZABLE最高隔离级别(基础系列收尾篇)

前言 对于上述锁其实是一个老生常谈的话题了,但是我们是否能够很明确的知道在什么情况下会存在上述各种锁类型呢,本节作为SQL Server系列末篇我们 来详细讲解下。 Range-Lock ...
  • duzanuolu
  • duzanuolu
  • 2017年03月19日 02:46
  • 78

SQL Server的四种隔离级别知识点

SQL Server的四种隔离级别知识点
  • sqlchen
  • sqlchen
  • 2016年08月25日 17:12
  • 378
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SQL Server读提交快照隔离级别的注意事项
举报原因:
原因补充:

(最多只允许输入30个字)