在今天的文章里,我想谈下在线索引重建操作( Online Index Rebuild operations),它们在SQL Server 2014里有怎样的提升。我们都知道,自SQL Server 2005开始引入了在线索引重建操作。但这些在线操作并非真正的在线操作,因为在操作开始时,SQL Server需要获得共享表锁(Shared Table Lock (S) ),在操作结束时需要在对应表上获得架构修改锁(Schema Modification Lock (Sch-M) )。因此这些操作是真正的在线操作,只是营销技巧(marketing trick)。但是,亲,“在线”肯定比“部分在线”好听多了。

尽管如此,SQL Server 2014还是在在线索引重建的开始和结束发生的阻塞做了一些改进。因此,在你执行在线索引重建时,你可以定义所谓的锁优先级(Lock Priority)。来看看下面的代码,你会看到起作用的新语法:

 ALTER INDEX idx_Col1 ON Foo REBUILD
WITH
(
ONLINE = ON
(
WAIT_AT_LOW_PRIORITY
(
MAX_DURATION = 1,
ABORT_AFTER_WAIT = SELF
)
)
)
GO

当阻塞情况发生时,你可以用WAIT_AT_LOW_PRIORITY关键字定义如何处理。使用第1个属性MAX_DURATION指定你想要等待的时间——这里是分钟,不是秒!用ABORT_AFTER_WAIT属性你指定哪个会话需要被SQL Server回滚。SELF意味着那个ALTER INDEX REBUILD语句会回滚,当你指定BLOCKERS时,阻塞的会话会回滚。当然,当没有阻塞发生时,在线索引重建操作会立即执行。因此这里你只能配置当阻塞情况发生时要怎么处理。

好了,我们来实操下。我们新建一个数据库,一个简单的表和一个聚集索引。

 -- Creates a new database
CREATE DATABASE Test
GO -- Use the database
USE Test
GO -- Create a simple table
CREATE TABLE Foo
(
Col1 INT IDENTITY(1, 1) NOT NULL,
Col2 INT NOT NULL,
Col3 INT NOT NULL
)
GO -- Create a unique Clustered Index on the table
CREATE UNIQUE CLUSTERED INDEX idx_Col1 ON Foo(Col1)
GO -- Insert a few test records
INSERT INTO Foo VALUES (1, 1), (2, 2), (3, 3)
GO

为了触发阻塞,我在不同的会话开始一个新的事务,但不提交:

 BEGIN TRANSACTION

 UPDATE Foo SET Col2 = 2
WHERE Col1 = 1

这意味着我们在需要修改的记录上获得排它锁(Exclusive Lock (X)),在对应的页上获得意向排它锁(Intent-Exclusive Lock (IX)),在表本身获得意向排它锁(Intent-Exclusive Lock (IX))。我们刚刚在SQL Server里创建了典型的锁定层次(locking hierarchy):表=>页=>记录。在表级别的意向排它锁(IX Lock)和在线索引重建操作需要的共享锁(Shared Lock)是不兼容的——典型的锁/阻塞情形发生了。当你现在执行在线索引重建操作时,会发生阻塞:

 ALTER INDEX idx_Col1 ON Foo REBUILD
WITH
(
ONLINE = ON
)
GO

当你查看DMV sys.dm_tran_locks时,你会看到那个需要共享锁(Shared Lock(S))的会话需要等待。这个会话会永远等待。我刚才就说过:“部分在线”……

 SELECT * FROM    sys.dm_tran_locks

当我们执行带有锁优先级(Lock Priority)的在线索引重建时,有趣的事情发生了:

 -- Perform an Online Index Rebuild
ALTER INDEX idx_Col1 ON Foo REBUILD
WITH
(
ONLINE = ON
(
WAIT_AT_LOW_PRIORITY
(
MAX_DURATION = 1,
ABORT_AFTER_WAIT = SELF
)
)
)
GO

在这个情况下,我们的ALTER INDEX语句会等待1分钟(MAX_DURATION),然后语句本身取消了(ABORT_AFTER_WAIT)。

如果你在这里指定了BLOCKERS选项,那么阻塞的会话就会回滚。当我们同时(在1分钟期间)查看DMV sys.dm_tran_locks,我们看到了有趣的东西:

从图中可以看到,SQL Server这里请求一个LOW_PRIORITY_WAIT的状态。因此3个请求状态(GRANT,WAIT,CONVERT)有了第4个选项:LOW_PRIORITY_WAIT。当我们查看DMV sys.dm_os_waiting_tasks时,事情变得有意思(59是执行语句的会话ID):

 SELECT * FROM sys.dm_os_waiting_tasks WHERE session_id=''

在线索引重建操作的等待会话报告了一个新的等待类型LCK_M_S_LOW_PRIORITY。这意味着当在线索引重建操作被阻塞时,我们可以从服务器级别(sys.dm_os_wait_stats)的等待统计信息里获得——不错!

但是LCK_M_S_LOW_PRIORITY并不是新的等待类型。在SQL Server 2014里,当你查看DMV sys.dm_os_wait_stats时,会看到21个新的等待类型:

 SELECT * FROM sys.dm_os_wait_stats WHERE wait_type LIKE '%LOW_PRIORITY%'
  • LCK_M_SCH_S_LOW_PRIORITY
  • LCK_M_SCH_M_LOW_PRIORITY
  • LCK_M_S_LOW_PRIORITY
  • LCK_M_U_LOW_PRIORITY
  • LCK_M_X_LOW_PRIORITY
  • LCK_M_IS_LOW_PRIORITY
  • LCK_M_IU_LOW_PRIORITY
  • LCK_M_IX_LOW_PRIORITY
  • LCK_M_SIU_LOW_PRIORITY
  • LCK_M_SIX_LOW_PRIORITY
  • LCK_M_UIX_LOW_PRIORITY
  • LCK_M_BU_LOW_PRIORITY
  • LCK_M_RS_S_LOW_PRIORITY
  • LCK_M_RS_U_LOW_PRIORITY
  • LCK_M_RIn_NL_LOW_PRIORITY
  • LCK_M_RIn_S_LOW_PRIORITY
  • LCK_M_RIn_U_LOW_PRIORITY
  • LCK_M_RIn_X_LOW_PRIORITY
  • LCK_M_RX_S_LOW_PRIORITY
  • LCK_M_RX_U_LOW_PRIORITY
  • LCK_M_RX_X_LOW_PRIORITY

所有主要的等待类型(LCK_M_*)都有额外的锁优先级等待类型。这个非常酷,也非常强大,因为你很容易从中可以跟踪到为什么在线重建索引操作被阻塞。另外,对于分区切换(Partition Switching)也适用同样的技术(锁优先级(Lock Priorities)),因为在切换期间,操作也要在2个表(原表,目标表)上获取架构修改锁(Schema Modification Lock (Sch-M))。

我希望这篇文章可以让你理解SQL Server 2014里的锁优先级(Lock Priorities),还有为什么SQL Server里的“在线”操作实际上只是“部分在线”。

感谢关注!

参考文章:

https://www.sqlpassion.at/archive/2014/01/02/how-sql-server-2014-improves-online-operations-that-arent-online-operations/

SQL Server 2014如何提升非在线的在线操作的更多相关文章

  1. SQL Server 2014里的性能提升

    在这篇文章里我想小结下SQL Server 2014引入各种惊艳性能提升!! 缓存池扩展(Buffer Pool Extensions) 缓存池扩展的想法非常简单:把页文件存储在非常快的存储上,例如S ...

  2. SQL Server 2014,表变量上的非聚集索引

    从Paul White的推特上看到,在SQL Server 2014里,对于表变量(Table Variables),它是支持非唯一聚集索引(Non-Unique Clustered Indexes) ...

  3. 看完SQL Server 2014 Q/A答疑集锦:想不升级都难!

    看完SQL Server 2014 Q/A答疑集锦:想不升级都难! 转载自:http://mp.weixin.qq.com/s/5rZCgnMKmJqeC7hbe4CZ_g 本期嘉宾为微软技术中心技术 ...

  4. 在SQL Server 2014里,如何用资源调控器压制你的存储?

    在今天的文章里,我想谈下SQL Server 2014里非常酷的提升:现在你终于可以根据需要的IOPS来压制查询!资源调控器(Resource Governor)自SQL Server 2008起引入 ...

  5. SQL Server 2014新特性探秘(1)-内存数据库

    简介    SQL Server 2014提供了众多激动人心的新功能,但其中我想最让人期待的特性之一就要算内存数据库了.去年我再西雅图参加SQL PASS Summit 2012的开幕式时,微软就宣布 ...

  6. SQL Server 2014新特性探秘(3)-可更新列存储聚集索引

    简介      列存储索引其实在在SQL Server 2012中就已经存在,但SQL Server 2012中只允许建立非聚集列索引,这意味着列索引是在原有的行存储索引之上的引用了底层的数据,因此会 ...

  7. SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变

    前提  本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段 ...

  8. 在SQL Server 2014里可更新的列存储索引 (Updateable Column Store Indexes)

    传统的关系数据库服务引擎往往并不是对超大量数据进行分析计算的最佳平台,为此,SQL Server中开发了分析服务引擎去对大笔数据进行分析计算.当然,对于数据的存放平台SQL Server数据库引擎而言 ...

  9. sql server 2014预览版发布

    MSDN发布sql server2014预览版,如下图: SQL Server 2014新特性: 微软SQL Server部门主管Eron Kelly介绍,通过将交易处理放到内存中进行,新的SQL S ...

随机推荐

  1. Visual Studio Xamarin编译Android项目出错的解决办法

    安装完Xamarin后,编译Android项目时,你会发现好长时间进度都不动,当你取消编译后,会发现其实是出错了,就是因在Android项目在第一次编译时要去google网站上下一个andorid s ...

  2. WebRTC实现网页版多人视频聊天室

    因为产品中要加入网页中网络会议的功能,这几天都在倒腾 WebRTC,现在分享下工作成果. 话说 WebRTC Real Time Communication 简称 RTC,是谷歌若干年前收购的一项技术 ...

  3. SWT: 发起事件 post event

    有很多学习SWT的同志遇到过一类需求,为某些控件添加了诸如MouseListener.KeyListener之类的监听,然后呢,希望使用代码模拟鼠标.键盘来执行点击.按键等操作. 首先说明一点,这是可 ...

  4. AlwaysON 故障处理之辅助副本磁盘空间不足

    用户反馈AlwaysON辅助副本数据库查询的结果与主库不一致, 远程到服务器后发现数据库的状态显示为“未同步/可疑”, 查看数据库的日志,定位到出现错误的时间点,可以看到提示日志文件所在磁盘的“磁盘空 ...

  5. 细说.NET 中的多线程 (一 概念)

    为什么使用多线程 使用户界面能够随时相应用户输入 当某个应用程序在进行大量运算时候,为了保证应用程序能够随时相应客户的输入,这个时候我们往往需要让大量运算和相应用户输入这两个行为在不同的线程中进行. ...

  6. 达洛克战记3 即将开服! What's New!

    历经数个月的开发,达洛克战记3即将全新开服! 剧情: 回归到三大种族起源时期,三大种族并没有像现在三足鼎立.人类一直处于统治地位.但是突然间一群巨人的出现,让人类损失惨重,身为勇者,需要探索巨人背后的 ...

  7. jQuery.fn.extend(object) object中this的指向

    看到下面的代码后,一下子懵逼了.这个this指向哪儿去了. jQuery.fn.extend({ check: function() { return this.each(function() { t ...

  8. Oracle+Jsp分页

    分页原理: 从jsp页面传到servlet请求中,可以获得当前点击的页数,第一次进入为首页,通过在servlet中获得的当前页数,并且设计一次性显示的内容数,就是几条信息, 并且从dao层查询到数据库 ...

  9. DDD~领域层

    回到目录 再论Domain与Infrastructure 在面向领域的设计中,领域层(Domain)实现上是位于最底层的,其它层有对它的引用,包括基础设施层(Infrastructure)也是去引用领 ...

  10. lua实现深度拷贝table表

    lua当变量作为函数的参数进行传递时,类似的也是boolean,string,number类型的变量进行值传递.而table,function,userdata类型的变量进行引用传递.故而当table ...