我想减少服务器上的锁定,因为我的应用程序中的某些用户对数据库具有直接权限,并且他们执行查询时不会NOLOCK
在数据库中创建锁定。
为了减少这种情况,我想为数据库创建一个新模式,在这个模式中,我将在数据库中存在的所有表上创建视图。在这个视图中,我将写为:
select * from TABLE_NAME(nolock).
然后我将只为这个模式的用户授予权限,这样可以减少锁定。
这种方法是一个好方法吗?它会在数据库中产生开销吗?
请建议。
我想减少服务器上的锁定,因为我的应用程序中的某些用户对数据库具有直接权限,并且他们执行查询时不会NOLOCK
在数据库中创建锁定。
为了减少这种情况,我想为数据库创建一个新模式,在这个模式中,我将在数据库中存在的所有表上创建视图。在这个视图中,我将写为:
select * from TABLE_NAME(nolock).
然后我将只为这个模式的用户授予权限,这样可以减少锁定。
这种方法是一个好方法吗?它会在数据库中产生开销吗?
请建议。
从BOL on NOLOCK
( READUNCOMMITED
) 提示:
指定允许脏读。不发布共享锁来防止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻止当前事务读取锁定的数据。允许脏读可能会导致更高的并发性,但代价是读取数据修改,然后由其他事务回滚。 这可能会为您的事务产生错误,向用户提供从未提交的数据,或导致用户看到两次记录(或根本看不到)。
如果这对你来说是可以接受的,你可以考虑你的方法。当然,它会加快所有查询的性能。但是我必须说这不是一个好主意,因为它可能会导致许多其他不可预知的错误 - 如果您将数据读取NOLOCK
用于以后的操作。
这是一篇不错的博客文章,介绍了使用的危险NOLOCK
以及您可以实施以避免使用它的其他可能的解决方案。
不,你的方法在很多层面都有缺陷。至少您需要了解两个问题:
READUNCOMMITTED 和 NOLOCK 提示仅适用于数据锁。所有查询,包括带有 READUNCOMMITTED 和 NOLOCK 提示的查询,都会在编译和执行期间获取 Sch-S(模式稳定性)锁。因此,当并发事务在表上持有 Sch-M(模式修改)锁时,查询会被阻止。
您应该考虑两种选择:
最好为这些用户创建数据库的备用只读副本以运行他们的查询。您可以使用AG 可读辅助(豪华选项)、备用日志传送数据库、本地数据库快照,或者作为最后一个选项,复制。
作为替代方案,在数据库中启用已提交读快照并让行版本控制消除争用。这可以说是一个更糟糕的选择,让用户查询备用数据,因为行版本控制会消耗资源,并且因为有权访问读写数据的用户可能会意外地最终修改数据甚至修改模式。
无论您选择什么,只要确保您摆脱了 NOLOCK。它没有帮助,它不起作用。