Answers:
从SSMS查询生产数据库时,我使用READ_UNCOMMITTED
(或NOLOCK
),但从应用程序代码中不常规地使用。这种做法(连同MAXDOP 1查询提示)有助于确保对数据进行分析和故障排除的临时查询不会影响生产工作负载,并且理解结果可能不正确。
可悲的是,我看到READ_UNCOMMITTED
/ NOLOCK
在生产代码中广泛使用了它,以避免以牺牲数据完整性为代价进行阻塞。正确的解决方案是行版本隔离级别(SNAPSHOT
或READ_COMMITTED
使用READ_COMMITTED_SNAPSHOT
数据库选项ON
)和/或注意查询和索引调整。
我最近的代码审查了一个proc,其中唯一的更改是删除,NOLOCK
因为它有时返回错误的结果。删除NOLOCK
是一件好事,但是,由于知道丢失或重复的行通常在大型表的分配顺序扫描期间发生,因此我建议也进行重构以使用一种UNION ALL
技术来提高索引的使用效率。现在,查询将在几毫秒内运行,并获得正确的结果,这是世界上最好的。
我认为,在某些情况下,只要您接受后果并没有其他选择,就可以了。
对于其他选项,我会促使人们朝着对新应用程序使用读取提交快照隔离(RCSI)或对较旧应用程序使用SNAPSHOT ISOLATION(SI)的问题,在这些情况下,您无法轻松地针对RCSI的竞争条件测试整个代码库。
但是,这些可能不适合。您可能需要花费一些额外的时间来爱护和照顾tempdb,并确保没有人留下一个使版本存储(和tempdb)增长并填满磁盘的开放事务。
如果您没有DBA,或者没有人监视或管理SQL Server,那么这些选择可能很危险。更一般而言,并不是每个人都完全控制进入其服务器的代码,他们可以在其中更改连接字符串或代码以请求SI进行问题查询。
除此之外,大多数人的整个应用程序都不会遇到锁定问题。他们遇到诸如报告OLTP数据之类的问题。如果您可以接受NOLOCK / RU的权衡以换取那些未被编写者阻止的报告,那么就去吧。
只要确保您了解这意味着什么。这并不意味着您的查询没有任何锁,而是意味着它不尊重其他查询所取得的锁。
当然,如果您的问题是写程序/写程序锁定,唯一有用的选择是SI,但是开发人员需要花费大量的工作才能通过错误处理等适当地实现它。
我们一直在医疗保健中使用它。
在查询中更改单个数据行的情况极为罕见,其读/写比约为10,000 / 1-其中大多数是插入而不是更新。例如,当实验室界面将患者的实验室结果写入数据库时,这些值将永远不会改变。
当数据确实更改时,它一次更改一行。没有人会更新整个列(DBA除外,否则它们会变得很糟)。
另一方面,我们运行了一堆查询来扫描诸如患者在72小时或更短时间内返回急诊室的事情,这绝对会打击表格。
在10年的医疗SQL中,我从未见过Rollback Transaction
。我想进出不影响最终用户的体验。如果存在降低OLTP数据库速度的高风险和获得不良数据的低风险,我将采取NOLOCK。
我们应该使用它吗?也许吧,也许不是。一般而言,我不会说我从事的许多应用程序数据库都经过精心设计。它们通常充满反模式。