在针对 SQL Server 2014 SP1 的 Cumulative Update #6 更新中,NOLOCK 指令中断。因此,依赖 NOLOCK 指令的数据库可能会意外地经历阻塞或是死锁。根据 SQL Server Release Services 博客最新更新的一篇文章,具体的情景是这样的:
在默认的基于锁的隔离级别或更高的隔离级别下,执行并行的 SELECT (…) INTO Table FROM
SourceTable 语句,特别当使用 NOLOCK 提示时。在这种情况下其他试图访问 SourceTable 的查询将阻塞。当一个事务持有对象的排他锁(例如进行中的表更新),另外一个事务正在执行并行的 SELECT (…) FROM
SourceTable,并使用 NOLOCK 提示。在这种情况下,尝试访问 SourceTable 的 SELECT 查询将被阻塞。
根据 Microsoft 发布团队的成员 Pedro Lopes 所说,这个错误不会影响使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 的代码。
早在推出行级版本(row level versioning),又称快照隔离之前,NOLOCK 提示就经常需要避免阻塞和死锁。然而,使用它会有一些风险。通过设计,运行NOLOCK 的查询可以读取在事务中改变的数据。这代表着决策可以基于最终回滚的事务。同样,决策也可以基于局部更新,例如使用一个记录的新版本和另一个相关记录的旧版本。
由于这些原因,一般不赞成在新的数据库中使用NOLOCK(和READ UNCOMMITTED)。然而,我们不能简单地将现有的数据库转移到行级版本。虽然它可以在不发生脏读的情况下解决阻塞问题,但是它还是需要增加tempdb 使用的成本。
Brent Ozar Unlimited 提供了一款通知服务,当问题解决的时候通知所有 DBA。你可以在 sqlserverupdates.com 报名。
查看英文原文: NOLOCK is Broken in SQL Server 2014 SP1
感谢张龙对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论