什么时候适合使用NOLOCK?
我在一些长时间运行的查询中时不时地遇到超时问题和死锁。
我想知道什么时候使用NOLOCK最合适,在哪里使用?
我是否在更新和更新中使用它? 插入? 或阅读?
I am having timeout issues and deadlocks from time to time with some long running queries.
I'm wondering when is it most appropriate to use NOLOCK and where?
Do I use it on the updates & inserts? or reads?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
请注意,您可以在每个表的基础上指定 nolock。
我通常在复杂的 SELECT 查询中使用 nolock,但仅适用于几乎从未更改的小型查找表以及仅显示的数据。 你知道列出当前半年价格的表格,或者查找字符串等的 id。这些东西只会随着重大更新而改变,之后服务器通常会定期重新启动。
这显着提高了性能,减少了最繁忙时间发生死锁的机会,更重要的是,对于涉及大量表的查询来说,在最坏的情况下,这一点确实很明显(这是合乎逻辑的,它们必须获得更少的锁,而那些 sidetables几乎到处都会用到,通常从 7-8 个表减少到需要锁定的 4 个表)
但是添加它要非常小心,不要着急,也不要例行公事地这样做。 如果使用得当,它不会造成伤害,但如果使用不当,就会造成严重伤害。
不要将它用于高度关键的东西,计算的东西等,因为它会变得不一致,任何迟早会导致写入的东西。
另一个这样的优化是 ROWLOCK,它只在行级别上锁定。 这在更新(或删除)行彼此不相关的表时非常有用,例如仅放入日志记录的表(并且它们的插入顺序并不重要)。 如果您有一个方案,在事务结束时将日志记录写入某个表,这也可以大大加快速度。
如果您的数据库的写入百分比相对较低,则可能不值得。 我的读:写比率低于 2:1。
我在处理此问题时保存的一些网址:
http://www.developerfusion .com/article/1688/sql-server-locks/4/
Note that you can specify nolock on a per table basis.
I typically used nolock in complex SELECT queries, but only for the little lookup tables that almost never changed, and for display-only data. You know the tables that list the prices for the current half year, or lookups of ids to strings etc. Stuff that only changes with major updates after which the servers are usually restarted routinely anyway.
This improved performance significantly, reduced the chance of deadlock in the busiest times, and more importantly it was really noticable during the worst case moments for queries that touched a lot of tables (which is logical, they have to obtain less locks, and those sidetables are often used nearly everywhere, often decreasing from 7-8 to 4 tables that need to be locked)
But be very careful adding it, don't rush it, and don't do it routinely. It won't hurt when used properly, but it will hurt horribly when used improperly.
Don't use it for highly critical stuff, stuff that calculates etc, because it will get inconsistent, anything that leads to a write sooner or later.
Another such optimization is ROWLOCK, which only locks on row level. This is mainly useful when updating (or deleting in) tables where the rows are not related to eachother, like tables where you only put in log records (and the order in which they are inserted doesn't matter). If you have a scheme that somewhere in the end of an transaction a log record is written to some table, this can speed up considerably too.
If your database has a relatively low percentage writes it might not be worth it. I had a read:write ratio of under 2:1.
Some URLs I saved when working on this:
http://www.developerfusion.com/article/1688/sql-server-locks/4/
SQL Server 中有四种事务隔离级别:
对于它所应用的表,NOLOCK 相当于“未提交的读”。 这意味着您可以看到将来可能回滚的事务中的行,以及许多其他奇怪的结果。
尽管如此,nolock 在实践中仍然表现良好。 特别是对于只读查询,显示稍微错误的数据并不是世界末日,例如业务报告。 我会避免在更新或插入附近,或者通常在决策代码附近的任何地方使用它,特别是当它涉及发票时。
作为 nolock 的替代方案,请考虑“读取已提交快照”,它适用于读取活动较多且写入活动较少的数据库。 您可以通过以下方式打开它:
它适用于 SQL Server 2005 及更高版本。 这就是 Oracle 默认的工作方式,也是 stackoverflow 本身使用的方式。 甚至还有一个关于它的编码恐怖博客条目。
PS 长时间运行的查询和死锁也可能表明 SQL Server 正在使用错误的假设。 检查您的统计数据或索引是否已过期:
应在每周维护计划中更新统计数据。
There are four transaction isolation levels in SQL Server:
For the tables it's applied to, NOLOCK is the equivalent of "read uncommitted". That means you can see rows from transactions that might be rolled back in the future, and many other strange results.
Still, nolock works very well in practice. Especially for read-only queries where displaying slightly wrong data is not the end of the world, like business reports. I'd avoid it near updates or inserts, or generally anywhere near decision making code, especially if it involves invoices.
As an alternative to nolock, consider "read committed snapshot", which is meant for databases with heavy read and less write activity. You can turn it on with:
It is available for SQL Server 2005 and higher. This is how Oracle works by default, and it's what stackoverflow itself uses. There's even a coding horror blog entry about it.
P.S. Long running queries and deadlocks can also indicate SQL Server is working with wrong assumptions. Check if your statistics or indexes are out of date:
Statistics should be updated in a weekly maintenance plan.
使用 nolock 作为最后的手段。 大多数死锁问题可以通过调整查询和/或调整索引来解决。 我想我在过去 5 年里见过一个僵局,而且无法通过调整两者之一来解决。
另请注意,NOLOCK 仅适用于 select 语句。 数据修改将始终锁定,该行为无法更改。 因此,如果遇到写入器/写入器死锁(很常见),那么没有锁根本没有帮助。
另请注意,nolock 除了返回脏数据之外,还可能导致重复行(从基础表中读取两次的行)和丢失行(基础表中根本未读取的行)。
Nolock 本质上对 SQL Server 来说意味着“我不介意我的结果是否稍微不准确”,
快照隔离是一个选项。 只需确保您首先仔细测试,因为 TempDB 上的负载增加可能会非常严重,具体取决于事务的频率和持续时间。 另请注意,虽然您不会在快照隔离中看到死锁,但可能会出现更新冲突。 再次测试并确保您的应用程序正常工作并且可以处理出现的任何错误。
Use nolock as a last resort. Most deadlock problems can be fixed by tuning the queries and/or tuning the indexes. I think I've seen one deadlock in the last 5 years that couldn't be fixed by tuning one of the two.
Also note that NOLOCK is only honoured on select statements. Data modifications will always lock, that behaviour cannot be changed. So if you're got a writer/writer deadlock (quite common), no lock won't help at all.
Also be aware that nolock, in addition to returning dirty data can result in duplicate rows (rows read twice from the underlying table) and missing rows (rows in the underlying table that weren't read at all).
Nolock essentially means to SQL Server 'I don't mind if my results are slightly inaccurate'
Snapshot isolation is an option. Just make sure that you test carefully first as the increased load on TempDB can be quite severe, depending how frequent and long your transactions are. Also note that while you won't see deadlocks in snapshot isolation, you can get update conflicts. Again, test and make sure that your apps work properly and can handle any errors that they get.
当脏读和幻像记录可以接受时使用它,即您可能定期运行非关键报告,其中信息的准确性不是主要驱动因素,但查看记录量或其他一些指标才是主要驱动因素,例如
Use it when it is acceptable to have dirty reads and phantom records I.e you may have non critical reports running regularly where the accuracy of the information is not a primary driver but having a view on volume of records is, or some other metric, for example
当可以读取脏数据时,应该使用 nolock。 可能对数据库进行大量更改的大型事务可能仍在进行中,使用 nolock 将仅返回迄今为止设置的数据。 如果该事务随后回滚,您正在查看的数据可能是错误的。 因此,只有在返回的结果可能是错误的情况下才应该使用它。
死锁是一个常见问题,但十分之九完全是由开发人员问题引起的。 我会集中精力寻找死锁的原因,而不是使用 nolock。 这很可能只是一笔交易以与其他所有交易不同的顺序进行操作。 解决这一问题可能会让所有问题消失。
You should use nolock when it is ok to read dirty data. A large transaction that may make a number of changes to the database may still be in progress, using nolock will just return the data it has set so far. Should that transaction then rollback the data you are looking at could be wrong. Therefore, you should only use it when it doesn't matter that what you get back could be wrong.
Deadlocks are a common problem, but 9 times out of 10 are entirely caused by a developer problem. I would concentrate on finding the cause of the deadlocks rather than using nolock. It is more than likely just one transaction doing things in a different order to all the others. Fixing just that one may make all your issues vanish.
对于没有读锁的事务一致视图,建议在 SQL Server 中启用快照隔离。
这与 NOLOCK 略有不同,因为当您读取信息时,结果始终反映已提交数据的版本,而不是查看未提交数据的可能性。 这提供了与 NOLOCK(无“读”锁)相同的锁定并发性,并具有更清晰的结果。
人们应该始终记住,即使具有事务一致性,您随后显示或在显示时使用的数据也可能是错误的或过时的。 我见过太多人认为,如果他们使用数据的速度足够快,或者如果他们在查询/事务中使用数据,那就没问题。 这是荒谬的——我认为可重复的一致性级别一开始就不应该被实现,因为它只会鼓励不良行为。 它们在 Oracle 中不存在。
就我个人而言,我喜欢禁用某些非关键数据视图和报告的锁定,因为它会减轻系统的负载,并且提供稍微不准确的结果的小概率也不是问题。
利用可重复的读取一致性级别并犯下诸如为用户输入保留开放事务之类的错误,对于开发人员来说,在初始开发方面可能会更容易一些,但几乎总是会导致合理扩展应用程序的主要障碍。
我的观点是,最好的方法始终是“仔细检查”条件,这些条件仍然必须为真,以便将更新应用于任何数据。
不好:
更好:
更好:
最后,应用程序必须检查行数,以确保在向用户呈现成功反馈之前实际更新了预期的行数。
For a transactionally consistent view without read locks recommend enabling snapshot isolation in SQL Server.
This is slightly different than NOLOCK in that when you read information the results always reflect a version of committed data rather than the possibility of viewing uncommited data. This provides the same locking concurrency as NOLOCK (no "read" locks) with clearer results.
One should always keep in mind even with transactional consistency the data you then go on to display or use at the time of it being displayed can possibly be wrong or outdated anyway. I've seen too many people assume that if they use the data fast enough or if they use it within a query/transaction that it's OK. This is absurd -- it is my opinion repeatable consistency levels should never have been implemented in the first place as it just encourages bad behavior. They do not exist in Oracle.
Personally I'm fond of disabling locking for certain non-critical data views and reports as it puts less of a load on the system and the small proboablitiy of providing slightly inaccurate results is not an issue.
Taking advantage of repeatable read consistency levels and committing sins such as holding open transactions for user input might be a little easier on the developer in terms of initial development but will almost always lead to major road"blocks" to any hope of reasonably scaling your application.
My view is the best approach is always to "double check" conditions that still must be true in order to apply updates to any data.
Bad:
Better:
Better still:
Finally the application must check row count to make sure the expected number of rows were actually updated before presenting success feedback to the user.