从一个不断插入数据的表格中选择数据

6

我应该如何从被不断插入数据的表中提取数据,而不会引起任何锁定以使插入操作继续进行。

我查看了一些资料并发现了使用select with nolock选项,但是,如果我理解正确的话,这并不阻止锁的创建,而是绕过当前的锁,抓取所有内容?

谢谢。

编辑:这个表将永远不会被更新,只会进行插入和选择操作。


在使用NOLOCKNO COMMIT级别时可以工作(尽管您可能会获得脏读取),但您应该能够安全地使用READ COMMITTED(或等效级别)。因为您没有进行更新,所以不应该出现锁争用问题(它将跳过所有已插入但尚未提交的内容)。 - Clockwork-Muse
是的,脏读绝对不是我想要的,因为这个过程非常重要。我发现我将从多个来源每分钟进行约250次插入,并且我希望确保这些插入可以继续进行而不会被我的选择语句阻塞。我没有计划建立索引,因为索引很快就会被分段(或者我认为是这样)。 - Antares
我对它们的实现不是很了解(而且我从未使用过SQL Server),但我认为你的“聚集索引”(特别是在类似于“rowId”或“insertTimestamp”的情况下)可能以非碎片化的方式进行索引(还有其他人能够发表意见吗?)。 - Clockwork-Muse
我真的需要搞清楚事实,但知道答案的人不在,它大约是每分钟500到600个插入 :-/ - Antares
5个回答

3

在从表中选择时,您可以使用NOLOCK提示。这样做会产生一些副作用(您基本上可以获得一个脏读取)。

NOLOCK在您添加它的查询中不会发出行锁,并且不会影响其他正在运行的查询发出的锁。NOLOCK确实会发出一个Sch-S锁,即模式稳定性锁,这不会给您带来问题。


谢谢,那我需要使用nolock选项,但有没有办法防止脏的未提交的部分? - Antares

3

我相信你有误解。使用 (nolock) 的 select 语句将不会获取任何锁。也就是说,它不会阻止其他写操作。

缺点似乎在于它将包括未提交的读取,因此结果可能在写入事务回滚时不可靠。


哦,那么在选择时没有阻止表格的情况下只读取已提交的行的方法吗? - Antares

3
只要您不介意从表中获取脏读取,这对您来说不应该是个问题。确保翻译隔离级别设置正确,并且您的调用代码(如果适用)不使用隐式事务,那么您就没问题了。
Microsoft的事务隔离文档: http://msdn.microsoft.com/en-us/library/ms173763.aspx NOLOCK是在遇到此类情况时常见且我认为被滥用的选项。虽然它可以帮助您克服高争用情况下的问题,但也可能导致难以跟踪的错误。虽然这是一个持续争论的问题,请查看http://blogs.msdn.com/b/davidlean/archive/2009/04/06/sql-server-nolock-hint-other-poor-ideas.aspx,了解使用此类提示的一些风险的想法。

嗯...所以使用nolock可能会导致数据完全丢失的巨大问题。这是一个重要的部分,不能出现这样的情况。在插入操作继续不受干扰的同时,有没有办法选择我想要的数据呢? - Antares
@Antares - 你在其他地方提到,你预计每秒钟会向表中插入一次数据。如果确实如此(大约每分钟60次插入),那么在这个时间范围内发出select查询不应该有任何问题。默认的隔离级别READ COMMITTED将防止脏读,在每分钟60次插入的情况下应该能够正常运行。http://msdn.microsoft.com/en-us/library/ms189122.aspx 你实际上是否在实践中遇到了问题,还是只是提前规划? - Carth
我只是提前规划。目前每个服务器都有自己的数据库进行写入,但我们将转移到一个中央数据库,所有这些服务器都将向其写入。我对我们正在进行的插入量产生了误解,在高峰时段,平均每分钟进行约250次插入。因此,我不仅要确保SELECT不会引起任何问题,而且我们将有7个服务器以每分钟35次的速度向这个表进行写入。 - Antares
我之前又犯了错误,但现在我知道这是正确的,因为我已经向那个知道的人确认过了。每分钟大约会有500-600次插入。 - Antares
@Antares - 你仍然远未超出 SQL Server 的能力范围(我假设你正在使用企业版)。如果你将其他服务器迁移到中央数据库,并注意到性能下降,那么你可以开始跟踪使用效率低下的问题。 - Carth

1

1

你可以使用NOLOCK,但我只会建议在那些你知道“脏数据”是可以接受的情况下使用(例如,一个syslog数据库,你知道一旦插入数据就不会被更改或删除)。最好的方法是从未被锁定的数据中进行SELECT;你能够识别哪些行没有受到你的插入影响吗?例如,如果你的数据是通过CreateDate列默认为GETDATE()来插入的,请确保你的查询从该点之前获取数据。

当然,这都取决于正在写入多少数据以及插入语句是否生成行、页或表锁定...


我相信每秒钟会有一个INSERT。 - Antares
我的错误,在运行数字后,我们平均每分钟大约有250个插入。 - Antares

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接