锁定 SQL Table/Row 并使用 NOLOCK/READPAST

Lock SQL Table/Row and using NOLOCK/READPAST

我是高度更新的 Microsoft SQL 服务器数据库的最终用户,其中包含数十个 table,每个数据库有数亿行。 银行数据库是我正在使用的一个很好的例子,除了在我的数据库中 UPDATE 语句被重新使用并且 INSERT 语句被频繁使用(一旦输入 table,它很少改变)。 我个人没有使用任何 UPDATE/INSERT 语句,仅使用 SELECT 语句(具有复杂的 WHERE/ JOIN/ CROSS/ GROUP 线索)。

我有一些关于锁定和使用的问题 NOLOCK/READPAST。

1.how 我可以知道我正在使用的查询是只锁定一行还是整个 table? 例如,我注意到这个查询并没有阻止其他用户将新数据插入 table:

SELECT *
FROM Table

虽然这个查询做了:

SELECT COUNT(Date)
FROM Table

这当然只是示例,并不是我正在使用的实际完整查询。 正如我提到的,行很少更改,因此锁定行与我无关,但锁定 table 非常令人担忧。

2.I 想知道在我的查询中使用 NOLOCK/READPAST 的风险(以消除我可能对锁定 table 以防止更新的任何担忧)。 我搜索了很多,但找不到完整的答案。 我不在乎如果使用 NOLOCK/READPAST 我可能会得到过去的数据(同样,我很少更改数据)或者我可能会错过一些新添加的数据。 我确实在几个地方读到使用 NOLOCK 可能会导致重复数据/损坏的数据,这对我来说是个问题。

3.whatREADPASY和NOLOCK到底有什么区别?关于上述问题,哪个更“安全”

谢谢。

  1. 这在很大程度上取决于您的服务器设置。一般来说,您希望锁定记录,即使您只是在读取它们也是如此,因为您不希望数据在读取时发生更改。这不仅会影响更新的记录,还会影响插入。您可以在此处了解有关读取提交和 snapshop 隔离的更多信息: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server

  2. 两者 NOLOCK/READPAST 都应该不惜一切代价避免。在极少数情况下这些是有意义的,但它们极为罕见。您最好优化查询以更好地执行并减少被锁定的记录数量和记录被锁定所花费的时间。我可以看到 NOLOCK 有用的一种情况是只有插入的日志 table,并且您的查询不会将数据连接到其他 table,并且脏记录不会导致问题.

  3. NOLOCK 不锁定它读取的记录。这里的风险是您正在阅读的记录可能会在阅读过程中发生字面上的变化。这意味着您可以开始读取记录并在进行更新之前获取某些列的一些值以及更新之后的一些列值。如果另一个事务回滚,您最终可能会读取从未真正提交给数据库的记录。 READPAST 跳过任何被锁定的行。如果另一个查询运行并且条件导致 100 行中的第 1-25 行被锁定,而您正在查询相同的数据,您将只能看到记录 26-100。对于您的查询,锁定的行不存在。 很棒的文章,包含详细信息: https://www.mssqltips.com/sqlservertip/4468/compare-sql-server-nolock-and-readpast-table-hints/

花时间学习优化查询以减少它们需要锁定的记录数量,并提高性能以使这些锁存在的时间保持在最低限度,你会得到更好的服务。